diff --git a/src/mbgl/map/raster_tile_data.cpp b/src/mbgl/map/raster_tile_data.cpp index 77ea8db89..6ab480401 100644 --- a/src/mbgl/map/raster_tile_data.cpp +++ b/src/mbgl/map/raster_tile_data.cpp @@ -23,10 +23,10 @@ void RasterTileData::parse() { } } -void RasterTileData::render(Painter &painter, const StyleLayer &layer_desc, const mat4 &matrix) { - bucket.render(painter, layer_desc, id, matrix); -} - -bool RasterTileData::hasData(StyleLayer const& /*layer_desc*/) const { - return bucket.hasData(); +Bucket* RasterTileData::getBucket(StyleLayer const&) { + if (bucket.hasData()) { + return &bucket; + } else { + return nullptr; + } } diff --git a/src/mbgl/map/raster_tile_data.hpp b/src/mbgl/map/raster_tile_data.hpp index dab2b7b84..45aee8f74 100644 --- a/src/mbgl/map/raster_tile_data.hpp +++ b/src/mbgl/map/raster_tile_data.hpp @@ -20,8 +20,7 @@ public: ~RasterTileData(); void parse() override; - void render(Painter &painter, const StyleLayer &layer_desc, const mat4 &matrix) override; - bool hasData(StyleLayer const &layer_desc) const override; + Bucket* getBucket(StyleLayer const &layer_desc) override; protected: StyleLayoutRaster layout; diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index 12684bb6c..6310a8588 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -184,16 +184,6 @@ void Source::drawClippingMasks(Painter &painter) { } } -void Source::render(Painter &painter, const StyleLayer &layer_desc) { - gl::group group(std::string { "layer: " } + layer_desc.id); - for (const auto& pair : tiles) { - Tile &tile = *pair.second; - if (tile.data && tile.data->state == TileData::State::parsed) { - painter.renderTileLayer(tile, layer_desc, tile.matrix); - } - } -} - void Source::finishRender(Painter &painter) { for (const auto& pair : tiles) { Tile &tile = *pair.second; diff --git a/src/mbgl/map/source.hpp b/src/mbgl/map/source.hpp index f7b675d16..fb2705aaf 100644 --- a/src/mbgl/map/source.hpp +++ b/src/mbgl/map/source.hpp @@ -29,7 +29,6 @@ class Sprite; class TexturePool; class Style; class Painter; -class StyleLayer; class TransformState; class Tile; struct ClipID; @@ -76,7 +75,6 @@ public: void updateMatrices(const mat4 &projMatrix, const TransformState &transform); void drawClippingMasks(Painter &painter); - void render(Painter &painter, const StyleLayer &layer_desc); void finishRender(Painter &painter); std::forward_list getLoadedTiles() const; diff --git a/src/mbgl/map/tile_data.hpp b/src/mbgl/map/tile_data.hpp index 92d9778fd..b85db7db7 100644 --- a/src/mbgl/map/tile_data.hpp +++ b/src/mbgl/map/tile_data.hpp @@ -47,8 +47,7 @@ public: // Override this in the child class. virtual void parse() = 0; - virtual void render(Painter &painter, const StyleLayer &layer_desc, const mat4 &matrix) = 0; - virtual bool hasData(StyleLayer const &layer_desc) const = 0; + virtual Bucket* getBucket(StyleLayer const &layer_desc) = 0; const TileID id; const std::string name; diff --git a/src/mbgl/map/vector_tile_data.cpp b/src/mbgl/map/vector_tile_data.cpp index 555e1851f..3dcbc0997 100644 --- a/src/mbgl/map/vector_tile_data.cpp +++ b/src/mbgl/map/vector_tile_data.cpp @@ -55,23 +55,15 @@ void VectorTileData::parse() { } } -void VectorTileData::render(Painter &painter, const StyleLayer &layer_desc, const mat4 &matrix) { - 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); - databucket_it->second->render(painter, layer_desc, id, matrix); +Bucket* VectorTileData::getBucket(StyleLayer const& layer) { + if (state == State::parsed && layer.bucket) { + const auto it = buckets.find(layer.bucket->name); + if (it != buckets.end()) { + assert(it->second); + if (it->second->hasData()) { + return it->second.get(); + } } } -} - -bool VectorTileData::hasData(const StyleLayer &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(); - } - } - return false; + return nullptr; } diff --git a/src/mbgl/map/vector_tile_data.hpp b/src/mbgl/map/vector_tile_data.hpp index 935ff9087..10eaf9c18 100644 --- a/src/mbgl/map/vector_tile_data.hpp +++ b/src/mbgl/map/vector_tile_data.hpp @@ -40,8 +40,7 @@ public: ~VectorTileData(); void parse() override; - void render(Painter &painter, const StyleLayer &layer_desc, const mat4 &matrix) override; - bool hasData(StyleLayer const& layer_desc) const override; + virtual Bucket* getBucket(StyleLayer const &layer_desc) override; protected: // Holds the actual geometries in this tile. diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 32d01c47f..903d12558 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -235,8 +235,11 @@ void Painter::render(const Style& style, TransformState state_, TimePoint time) // Actually render the layers if (debug::renderTree) { Log::Info(Event::Render, "{"); indent++; } + // Figure out what buckets we have to draw and what order we have to draw them in. + const auto order = determineRenderOrder(style); + // TODO: Correctly compute the number of layers recursively beforehand. - float strata_thickness = 1.0f / (style.layers.size() + 1); + const float strata_thickness = 1.0f / (order.size() + 1); // - FIRST PASS ------------------------------------------------------------ // Render everything top-to-bottom by using reverse iterators. Render opaque @@ -246,10 +249,16 @@ void Painter::render(const Style& style, TransformState state_, TimePoint time) Log::Info(Event::Render, "%*s%s", indent++ * 4, "", "OPAQUE {"); } int i = 0; - for (auto it = style.layers.rbegin(), end = style.layers.rend(); it != end; ++it, ++i) { - setOpaque(); - setStrata(i * strata_thickness); - renderLayer(**it); + setOpaque(); + for (auto it = order.rbegin(), end = order.rend(); it != end; ++it, ++i) { + const auto& item = *it; + if (item.bucket && item.tile) { + setStrata(i * strata_thickness); + prepareTile(*item.tile); + item.bucket->render(*this, item.layer, item.tile->id, item.tile->matrix); + } else { + renderBackground(item.layer); + } } if (debug::renderTree) { Log::Info(Event::Render, "%*s%s", --indent * 4, "", "}"); @@ -262,10 +271,14 @@ void Painter::render(const Style& style, TransformState state_, TimePoint time) Log::Info(Event::Render, "%*s%s", indent++ * 4, "", "TRANSLUCENT {"); } --i; - for (auto it = style.layers.begin(), end = style.layers.end(); it != end; ++it, --i) { - setTranslucent(); - setStrata(i * strata_thickness); - renderLayer(**it); + setTranslucent(); + for (auto it = order.begin(), end = order.end(); it != end; ++it, --i) { + const auto& item = *it; + if (item.bucket && item.tile) { + setStrata(i * strata_thickness); + prepareTile(*item.tile); + item.bucket->render(*this, item.layer, item.tile->id, item.tile->matrix); + } } if (debug::renderTree) { Log::Info(Event::Render, "%*s%s", --indent * 4, "", "}"); @@ -282,76 +295,58 @@ void Painter::render(const Style& style, TransformState state_, TimePoint time) } } -void Painter::renderLayer(const StyleLayer &layer_desc) { - if (layer_desc.bucket->visibility == VisibilityType::None) return; - if (layer_desc.type == StyleLayerType::Background) { - // This layer defines a background color/image. +std::vector Painter::determineRenderOrder(const Style& style) { + std::vector order; - if (debug::renderTree) { - Log::Info(Event::Render, "%*s- %s (%s)", indent * 4, "", layer_desc.id.c_str(), - StyleLayerTypeClass(layer_desc.type).c_str()); + for (const auto& layerPtr : style.layers) { + const auto& layer = *layerPtr; + if (layer.bucket->visibility == VisibilityType::None) continue; + if (layer.type == StyleLayerType::Background) { + // This layer defines a background color/image. + order.emplace_back(layer); + continue; } - renderBackground(layer_desc); - } else { // This is a singular layer. - if (!layer_desc.bucket) { - Log::Warning(Event::Render, "layer '%s' is missing bucket", layer_desc.id.c_str()); - return; + if (!layer.bucket) { + Log::Warning(Event::Render, "layer '%s' is missing bucket", layer.id.c_str()); + continue; } - if (!layer_desc.bucket->source) { - Log::Warning(Event::Render, "can't find source for layer '%s'", layer_desc.id.c_str()); - return; + if (!layer.bucket->source) { + Log::Warning(Event::Render, "can't find source for layer '%s'", layer.id.c_str()); + continue; } // 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; + if (layer.bucket->min_zoom > zoom || + layer.bucket->max_zoom <= zoom) { + continue; } - // 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().isVisible()) return; - break; - case StyleLayerType::Line: - if (pass == RenderPass::Opaque) return; - if (!layer_desc.getProperties().isVisible()) return; - break; - case StyleLayerType::Symbol: - if (pass == RenderPass::Opaque) return; - if (!layer_desc.getProperties().isVisible()) return; - break; - case StyleLayerType::Raster: - if (pass == RenderPass::Opaque) return; - if (!layer_desc.getProperties().isVisible()) return; - break; - default: - break; + // Don't include invisible layers. + if (!layer.isVisible()) { + continue; } - if (debug::renderTree) { - Log::Info(Event::Render, "%*s- %s (%s)", indent * 4, "", layer_desc.id.c_str(), - StyleLayerTypeClass(layer_desc.type).c_str()); - } + auto tiles = layer.bucket->source->getLoadedTiles(); + for (auto tile : tiles) { + assert(tile); + if (!tile->data) { + continue; + } - layer_desc.bucket->source->render(*this, layer_desc); + auto bucket = tile->data->getBucket(layer); + if (bucket) { + order.emplace_back(layer, tile, bucket); + } + } } -} -void Painter::renderTileLayer(const Tile& tile, const StyleLayer &layer_desc, const mat4 &matrix) { - assert(tile.data); - if (tile.data->hasData(layer_desc) || layer_desc.type == StyleLayerType::Raster) { - gl::group group(std::string { "render " } + tile.data->name); - prepareTile(tile); - tile.data->render(*this, layer_desc, matrix); - } + return order; } void Painter::renderBackground(const StyleLayer &layer_desc) { diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index e7e5557eb..be21ef2b6 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -57,6 +57,18 @@ class GaussianShader; struct ClipID; +struct RenderItem { + inline RenderItem(const StyleLayer& layer_, + const Tile* tile_ = nullptr, + Bucket* bucket_ = nullptr) + : tile(tile_), bucket(bucket_), layer(layer_) { + } + + const Tile* const tile; + Bucket* const bucket; + const StyleLayer& layer; +}; + class Painter : private util::noncopyable { public: Painter(SpriteAtlas&, GlyphAtlas&, LineAtlas&); @@ -75,11 +87,6 @@ public: TransformState state, TimePoint time); - void renderLayer(const StyleLayer&); - - // Renders a particular layer from a tile. - void renderTileLayer(const Tile& tile, const StyleLayer &layer_desc, const mat4 &matrix); - // Renders debug information for a tile. void renderTileDebug(const Tile& tile); @@ -131,6 +138,8 @@ private: void setupShaders(); mat4 translatedMatrix(const mat4& matrix, const std::array &translation, const TileID &id, TranslateAnchorType anchor); + std::vector determineRenderOrder(const Style& style); + void prepareTile(const Tile& tile); template diff --git a/src/mbgl/style/style_layer.cpp b/src/mbgl/style/style_layer.cpp index e9c301d8c..8713b73b1 100644 --- a/src/mbgl/style/style_layer.cpp +++ b/src/mbgl/style/style_layer.cpp @@ -13,6 +13,21 @@ bool StyleLayer::isBackground() const { return type == StyleLayerType::Background; } +bool StyleLayer::isVisible() const { + switch (type) { + case StyleLayerType::Fill: + return getProperties().isVisible(); + case StyleLayerType::Line: + return getProperties().isVisible(); + case StyleLayerType::Symbol: + return getProperties().isVisible(); + case StyleLayerType::Raster: + return getProperties().isVisible(); + default: + return false; + } +} + void StyleLayer::setClasses(const std::vector &class_names, const TimePoint now, const PropertyTransition &defaultTransition) { // Stores all keys that we have already added transitions for. diff --git a/src/mbgl/style/style_layer.hpp b/src/mbgl/style/style_layer.hpp index a00b7084f..774ed3901 100644 --- a/src/mbgl/style/style_layer.hpp +++ b/src/mbgl/style/style_layer.hpp @@ -35,6 +35,9 @@ public: // Determines whether this layer is the background layer. bool isBackground() const; + // Checks whether the layer is currently visible at all. + bool isVisible() const; + // Updates the StyleProperties information in this layer by evaluating all // pending transitions and applied classes in order. void updateProperties(float z, TimePoint now, ZoomHistory &zoomHistory);