diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/geometry/sprite_atlas.cpp | 53 | ||||
-rw-r--r-- | src/map/map.cpp | 170 | ||||
-rw-r--r-- | src/map/raster_tile_data.cpp | 2 | ||||
-rw-r--r-- | src/map/tile_data.cpp | 10 | ||||
-rw-r--r-- | src/map/tile_parser.cpp | 8 | ||||
-rw-r--r-- | src/map/transform.cpp | 66 | ||||
-rw-r--r-- | src/map/transform_state.cpp | 11 | ||||
-rw-r--r-- | src/map/vector_tile_data.cpp | 23 | ||||
-rw-r--r-- | src/renderer/painter.cpp | 192 | ||||
-rw-r--r-- | src/renderer/painter_debug.cpp | 10 | ||||
-rw-r--r-- | src/renderer/painter_fill.cpp | 18 | ||||
-rw-r--r-- | src/renderer/painter_line.cpp | 25 | ||||
-rw-r--r-- | src/renderer/painter_raster.cpp | 7 | ||||
-rw-r--r-- | src/renderer/painter_symbol.cpp | 65 | ||||
-rw-r--r-- | src/renderer/symbol_bucket.cpp | 5 |
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; |