diff options
Diffstat (limited to 'src/mbgl/tile/geometry_tile.cpp')
-rw-r--r-- | src/mbgl/tile/geometry_tile.cpp | 165 |
1 files changed, 116 insertions, 49 deletions
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 23b3737a38..8c018ce3aa 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -6,20 +6,20 @@ #include <mbgl/style/layers/background_layer.hpp> #include <mbgl/style/layers/custom_layer.hpp> #include <mbgl/renderer/tile_parameters.hpp> -#include <mbgl/renderer/render_background_layer.hpp> -#include <mbgl/renderer/render_custom_layer.hpp> -#include <mbgl/renderer/render_symbol_layer.hpp> -#include <mbgl/renderer/symbol_bucket.hpp> -#include <mbgl/style/style.hpp> +#include <mbgl/renderer/layers/render_background_layer.hpp> +#include <mbgl/renderer/layers/render_custom_layer.hpp> +#include <mbgl/renderer/layers/render_symbol_layer.hpp> +#include <mbgl/renderer/buckets/symbol_bucket.hpp> +#include <mbgl/renderer/query.hpp> +#include <mbgl/text/glyph_atlas.hpp> +#include <mbgl/renderer/image_atlas.hpp> #include <mbgl/storage/file_source.hpp> #include <mbgl/geometry/feature_index.hpp> #include <mbgl/text/collision_tile.hpp> #include <mbgl/map/transform_state.hpp> -#include <mbgl/map/query.hpp> -#include <mbgl/util/run_loop.hpp> #include <mbgl/style/filter_evaluator.hpp> -#include <mbgl/util/chrono.hpp> #include <mbgl/util/logging.hpp> +#include <mbgl/actor/scheduler.hpp> #include <iostream> @@ -27,32 +27,51 @@ namespace mbgl { using namespace style; +/* + Correlation between GeometryTile and GeometryTileWorker is safeguarded by two + correlation schemes: + + GeometryTile's 'correlationID' is used for ensuring the tile will be flagged + as non-pending only when the placement coming from the last operation (as in + 'setData', 'setLayers', 'setPlacementConfig') occurs. This is important for + still mode rendering as we want to render only when all layout and placement + operations are completed. + + GeometryTileWorker's 'imageCorrelationID' is used for checking whether an + image request reply coming from `GeometryTile` is valid. Previous image + request replies are ignored as they result in incomplete placement attempts + that could flag the tile as non-pending too early. + */ + GeometryTile::GeometryTile(const OverscaledTileID& id_, std::string sourceID_, - const TileParameters& parameters, - GlyphAtlas& glyphAtlas_, - SpriteAtlas& spriteAtlas_) + const TileParameters& parameters) : Tile(id_), sourceID(std::move(sourceID_)), - style(parameters.style), - mailbox(std::make_shared<Mailbox>(*util::RunLoop::Get())), + mailbox(std::make_shared<Mailbox>(*Scheduler::GetCurrent())), worker(parameters.workerScheduler, ActorRef<GeometryTile>(*this, mailbox), id_, obsolete, - parameters.mode), - glyphAtlas(glyphAtlas_), - spriteAtlas(spriteAtlas_), - placementThrottler(Milliseconds(300), [this] { invokePlacement(); }) { + parameters.mode, + parameters.pixelRatio), + glyphManager(parameters.glyphManager), + imageManager(parameters.imageManager), + lastYStretch(1.0f), + mode(parameters.mode) { } GeometryTile::~GeometryTile() { - glyphAtlas.removeGlyphs(*this); - spriteAtlas.removeRequestor(*this); - cancel(); + glyphManager.removeRequestor(*this); + imageManager.removeRequestor(*this); + markObsolete(); } void GeometryTile::cancel() { + markObsolete(); +} + +void GeometryTile::markObsolete() { obsolete = true; } @@ -68,7 +87,6 @@ void GeometryTile::setData(std::unique_ptr<const GeometryTileData> data_) { ++correlationID; worker.invoke(&GeometryTileWorker::setData, std::move(data_), correlationID); - redoLayout(); } void GeometryTile::setPlacementConfig(const PlacementConfig& desiredConfig) { @@ -82,7 +100,7 @@ void GeometryTile::setPlacementConfig(const PlacementConfig& desiredConfig) { ++correlationID; requestedConfig = desiredConfig; - placementThrottler.invoke(); + invokePlacement(); } void GeometryTile::invokePlacement() { @@ -91,29 +109,29 @@ void GeometryTile::invokePlacement() { } } -void GeometryTile::redoLayout() { +void GeometryTile::setLayers(const std::vector<Immutable<Layer::Impl>>& layers) { // Mark the tile as pending again if it was complete before to prevent signaling a complete // state despite pending parse operations. pending = true; - std::vector<std::unique_ptr<Layer>> copy; + std::vector<Immutable<Layer::Impl>> impls; - for (const Layer* layer : style.getLayers()) { - // Avoid cloning and including irrelevant layers. - if (layer->is<BackgroundLayer>() || - layer->is<CustomLayer>() || - layer->baseImpl->source != sourceID || - id.overscaledZ < std::floor(layer->baseImpl->minZoom) || - id.overscaledZ >= std::ceil(layer->baseImpl->maxZoom) || - layer->baseImpl->visibility == VisibilityType::None) { + for (const auto& layer : layers) { + // Skip irrelevant layers. + if (layer->type == LayerType::Background || + layer->type == LayerType::Custom || + layer->source != sourceID || + id.overscaledZ < std::floor(layer->minZoom) || + id.overscaledZ >= std::ceil(layer->maxZoom) || + layer->visibility == VisibilityType::None) { continue; } - copy.push_back(layer->baseImpl->clone()); + impls.push_back(layer); } ++correlationID; - worker.invoke(&GeometryTileWorker::setLayers, std::move(copy), correlationID); + worker.invoke(&GeometryTileWorker::setLayers, std::move(impls), correlationID); } void GeometryTile::onLayout(LayoutResult result, const uint64_t resultCorrelationID) { @@ -134,10 +152,16 @@ void GeometryTile::onPlacement(PlacementResult result, const uint64_t resultCorr pending = false; } symbolBuckets = std::move(result.symbolBuckets); - for (auto& entry : symbolBuckets) { - dynamic_cast<SymbolBucket*>(entry.second.get())->spriteAtlas = &spriteAtlas; - } collisionTile = std::move(result.collisionTile); + if (result.glyphAtlasImage) { + glyphAtlasImage = std::move(*result.glyphAtlasImage); + } + if (result.iconAtlasImage) { + iconAtlasImage = std::move(*result.iconAtlasImage); + } + if (collisionTile.get()) { + lastYStretch = collisionTile->yStretch; + } observer->onTileChanged(*this); } @@ -149,25 +173,51 @@ void GeometryTile::onError(std::exception_ptr err, const uint64_t resultCorrelat observer->onTileError(*this, err); } -void GeometryTile::onGlyphsAvailable(GlyphPositionMap glyphPositions) { - worker.invoke(&GeometryTileWorker::onGlyphsAvailable, std::move(glyphPositions)); +void GeometryTile::onGlyphsAvailable(GlyphMap glyphs) { + worker.invoke(&GeometryTileWorker::onGlyphsAvailable, std::move(glyphs)); } void GeometryTile::getGlyphs(GlyphDependencies glyphDependencies) { - glyphAtlas.getGlyphs(*this, std::move(glyphDependencies)); + glyphManager.getGlyphs(*this, std::move(glyphDependencies)); } -void GeometryTile::onIconsAvailable(IconMap icons) { - worker.invoke(&GeometryTileWorker::onIconsAvailable, std::move(icons)); +void GeometryTile::onImagesAvailable(ImageMap images, uint64_t imageCorrelationID) { + worker.invoke(&GeometryTileWorker::onImagesAvailable, std::move(images), imageCorrelationID); } -void GeometryTile::getIcons(IconDependencies) { - spriteAtlas.getIcons(*this); +void GeometryTile::getImages(ImageRequestPair pair) { + imageManager.getImages(*this, std::move(pair)); } -Bucket* GeometryTile::getBucket(const RenderLayer& layer) const { - const auto& buckets = layer.is<RenderSymbolLayer>() ? symbolBuckets : nonSymbolBuckets; - const auto it = buckets.find(layer.baseImpl.id); +void GeometryTile::upload(gl::Context& context) { + auto uploadFn = [&] (Bucket& bucket) { + if (bucket.needsUpload()) { + bucket.upload(context); + } + }; + + for (auto& entry : nonSymbolBuckets) { + uploadFn(*entry.second); + } + + for (auto& entry : symbolBuckets) { + uploadFn(*entry.second); + } + + if (glyphAtlasImage) { + glyphAtlasTexture = context.createTexture(*glyphAtlasImage, 0); + glyphAtlasImage = {}; + } + + if (iconAtlasImage) { + iconAtlasTexture = context.createTexture(*iconAtlasImage, 0); + iconAtlasImage = {}; + } +} + +Bucket* GeometryTile::getBucket(const Layer::Impl& layer) const { + const auto& buckets = layer.type == LayerType::Symbol ? symbolBuckets : nonSymbolBuckets; + const auto it = buckets.find(layer.id); if (it == buckets.end()) { return nullptr; } @@ -180,10 +230,20 @@ void GeometryTile::queryRenderedFeatures( std::unordered_map<std::string, std::vector<Feature>>& result, const GeometryCoordinates& queryGeometry, const TransformState& transformState, + const std::vector<const RenderLayer*>& layers, const RenderedQueryOptions& options) { if (!featureIndex || !data) return; + // Determine the additional radius needed factoring in property functions + float additionalRadius = 0; + for (const RenderLayer* layer : layers) { + auto bucket = getBucket(*layer->baseImpl); + if (bucket) { + additionalRadius = std::max(additionalRadius, bucket->getQueryRadius(*layer)); + } + } + featureIndex->query(result, queryGeometry, transformState.getAngle(), @@ -192,9 +252,9 @@ void GeometryTile::queryRenderedFeatures( options, *data, id.canonical, - style, + layers, collisionTile.get(), - *this); + additionalRadius); } void GeometryTile::querySourceFeatures( @@ -233,4 +293,11 @@ void GeometryTile::querySourceFeatures( } } +float GeometryTile::yStretch() const { + // collisionTile gets reset in onLayout but we don't clear the symbolBuckets + // until a new placement result comes along, so keep the yStretch value in + // case we need to render them. + return lastYStretch; +} + } // namespace mbgl |