diff --git a/include/llmr/map/map.hpp b/include/llmr/map/map.hpp index 649acfa69..af4250c35 100644 --- a/include/llmr/map/map.hpp +++ b/include/llmr/map/map.hpp @@ -52,7 +52,7 @@ public: void resize(uint16_t width, uint16_t height, float ratio, uint16_t fb_width, uint16_t fb_height); // Styling - const std::set> getActiveSources() const; + const std::set> getActiveSources() const; void setAppliedClasses(const std::vector &classes); void toggleClass(const std::string &name); const std::vector &getAppliedClasses() const; @@ -178,7 +178,7 @@ private: int indent = 0; - std::set> activeSources; + std::set> activeSources; private: bool async = false; diff --git a/include/llmr/renderer/painter.hpp b/include/llmr/renderer/painter.hpp index a465f657f..ef160eddd 100644 --- a/include/llmr/renderer/painter.hpp +++ b/include/llmr/renderer/painter.hpp @@ -34,6 +34,7 @@ class Style; class Tile; class GlyphAtlas; class Source; +class StyleSource; class FillBucket; class LineBucket; @@ -106,7 +107,7 @@ public: // Configures the painter strata that is used for early z-culling of fragments. void setStrata(float strata); - void drawClippingMasks(const std::set> &sources); + void drawClippingMasks(const std::set> &sources); void drawClippingMask(const mat4& matrix, const ClipID& clip); void clearFramebuffers(); diff --git a/include/llmr/style/style_bucket.hpp b/include/llmr/style/style_bucket.hpp index 0f3824211..5d8c9d6bb 100644 --- a/include/llmr/style/style_bucket.hpp +++ b/include/llmr/style/style_bucket.hpp @@ -76,7 +76,6 @@ public: std::string name; std::shared_ptr style_source; - std::shared_ptr source; std::string source_layer; FilterExpression filter; StyleBucketRender render = std::false_type(); diff --git a/include/llmr/style/style_source.hpp b/include/llmr/style/style_source.hpp index cf55e94be..e7b742abb 100644 --- a/include/llmr/style/style_source.hpp +++ b/include/llmr/style/style_source.hpp @@ -5,14 +5,19 @@ namespace llmr { -struct StyleSource { - const SourceType type; - const std::string url; - const uint32_t tile_size; - const int32_t min_zoom; - const int32_t max_zoom; +class Source; - StyleSource(SourceType type = SourceType::Vector, +struct StyleSource { + const SourceType type; + const std::string url; + const uint32_t tile_size; + const int32_t min_zoom; + const int32_t max_zoom; + + bool enabled = false; + std::shared_ptr source; + + StyleSource(SourceType type = SourceType::Vector, const std::string &url = "", uint32_t tile_size = 512, uint32_t min_zoom = 0, uint32_t max_zoom = 22) diff --git a/src/map/map.cpp b/src/map/map.cpp index 899b9534f..68db66370 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -411,11 +411,32 @@ void Map::setDefaultTransitionDuration(uint64_t duration_milliseconds) { } void Map::updateSources() { - activeSources.clear(); + // First, disable all existing sources. + for (const std::shared_ptr &source : activeSources) { + source->enabled = false; + } + + // Then, reenable all of those that we actually use when drawing this layer. updateSources(style->layers); + + // Then, construct or destroy the actual source object, depending on enabled state. + for (const std::shared_ptr &source : activeSources) { + if (source->enabled) { + if (!source->source) { + source->source = std::make_shared(*source, getAccessToken()); + } + } else { + source->source.reset(); + } + } + + // Finally, remove all sources that are disabled. + util::erase_if(activeSources, [](std::shared_ptr source){ + return !source->enabled; + }); } -const std::set> Map::getActiveSources() const { +const std::set> Map::getActiveSources() const { return activeSources; } @@ -427,8 +448,7 @@ void Map::updateSources(const std::shared_ptr &group) { if (!layer) continue; if (layer->bucket) { if (layer->bucket->style_source) { - auto ret = activeSources.emplace(std::make_shared(*layer->bucket->style_source, this->getAccessToken())); - layer->bucket->source = *ret.first; + (*activeSources.emplace(layer->bucket->style_source).first)->enabled = true; } } else if (layer->layers) { updateSources(layer->layers); @@ -437,23 +457,23 @@ void Map::updateSources(const std::shared_ptr &group) { } void Map::updateTiles() { - for (const std::shared_ptr &source : getActiveSources()) { - source->update(*this); + for (const std::shared_ptr &source : getActiveSources()) { + source->source->update(*this); } } void Map::updateRenderState() { std::forward_list ids; - for (const std::shared_ptr &source : getActiveSources()) { - ids.splice_after(ids.before_begin(), source->getIDs()); - source->updateMatrices(painter.projMatrix, state); + for (const std::shared_ptr &source : getActiveSources()) { + ids.splice_after(ids.before_begin(), source->source->getIDs()); + source->source->updateMatrices(painter.projMatrix, state); } const std::map clipIDs = computeClipIDs(ids); - for (const std::shared_ptr &source : getActiveSources()) { - source->updateClipIDs(clipIDs); + for (const std::shared_ptr &source : getActiveSources()) { + source->source->updateClipIDs(clipIDs); } } @@ -532,8 +552,8 @@ void Map::render() { // 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 std::shared_ptr &source : getActiveSources()) { - source->finishRender(painter); + for (const std::shared_ptr &source : getActiveSources()) { + source->source->finishRender(painter); } painter.renderMatte(); @@ -630,6 +650,8 @@ void Map::renderLayer(std::shared_ptr layer_desc, RenderPass pass) { return; } + StyleSource &style_source = *layer_desc->bucket->style_source; + // 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) { @@ -661,6 +683,8 @@ void Map::renderLayer(std::shared_ptr layer_desc, RenderPass pass) { << layer_desc->type << ")" << std::endl; } - layer_desc->bucket->source->render(painter, layer_desc); + if (style_source.source) { + style_source.source->render(painter, layer_desc); + } } } diff --git a/src/renderer/painter_clipping.cpp b/src/renderer/painter_clipping.cpp index 95e4b727f..25fe0658f 100644 --- a/src/renderer/painter_clipping.cpp +++ b/src/renderer/painter_clipping.cpp @@ -6,7 +6,7 @@ using namespace llmr; -void Painter::drawClippingMasks(const std::set> &sources) { +void Painter::drawClippingMasks(const std::set> &sources) { gl::group group("clipping masks"); useProgram(plainShader->program); @@ -18,8 +18,8 @@ void Painter::drawClippingMasks(const std::set> &sources coveringPlainArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0)); - for (const std::shared_ptr &source : sources) { - source->drawClippingMasks(*this); + for (const std::shared_ptr &source : sources) { + source->source->drawClippingMasks(*this); } glEnable(GL_DEPTH_TEST);