diff options
Diffstat (limited to 'src/mbgl/tile/geometry_tile.cpp')
-rw-r--r-- | src/mbgl/tile/geometry_tile.cpp | 151 |
1 files changed, 101 insertions, 50 deletions
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 4ab11d79fe..701e7cf2d6 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -10,17 +10,15 @@ #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> @@ -28,21 +26,40 @@ 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', 'setShowCollisionBoxes') 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) : Tile(id_), sourceID(std::move(sourceID_)), - mailbox(std::make_shared<Mailbox>(*util::RunLoop::Get())), + mailbox(std::make_shared<Mailbox>(*Scheduler::GetCurrent())), worker(parameters.workerScheduler, ActorRef<GeometryTile>(*this, mailbox), id_, + sourceID, obsolete, parameters.mode, - parameters.pixelRatio), + parameters.pixelRatio, + parameters.debugOptions & MapDebugOptions::Collision), glyphManager(parameters.glyphManager), imageManager(parameters.imageManager), - placementThrottler(Milliseconds(300), [this] { invokePlacement(); }) { + mode(parameters.mode), + showCollisionBoxes(parameters.debugOptions & MapDebugOptions::Collision) { } GeometryTile::~GeometryTile() { @@ -61,7 +78,6 @@ void GeometryTile::markObsolete() { void GeometryTile::setError(std::exception_ptr err) { loaded = true; - renderable = false; observer->onTileError(*this, err); } @@ -74,25 +90,6 @@ void GeometryTile::setData(std::unique_ptr<const GeometryTileData> data_) { worker.invoke(&GeometryTileWorker::setData, std::move(data_), correlationID); } -void GeometryTile::setPlacementConfig(const PlacementConfig& desiredConfig) { - if (requestedConfig == desiredConfig) { - return; - } - - // Mark the tile as pending again if it was complete before to prevent signaling a complete - // state despite pending parse operations. - pending = true; - - ++correlationID; - requestedConfig = desiredConfig; - placementThrottler.invoke(); -} - -void GeometryTile::invokePlacement() { - if (requestedConfig) { - worker.invoke(&GeometryTileWorker::setPlacementConfig, *requestedConfig, correlationID); - } -} 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 @@ -119,37 +116,47 @@ void GeometryTile::setLayers(const std::vector<Immutable<Layer::Impl>>& layers) worker.invoke(&GeometryTileWorker::setLayers, std::move(impls), correlationID); } -void GeometryTile::onLayout(LayoutResult result) { - loaded = true; - renderable = true; +void GeometryTile::setShowCollisionBoxes(const bool showCollisionBoxes_) { + if (showCollisionBoxes != showCollisionBoxes_) { + showCollisionBoxes = showCollisionBoxes_; + ++correlationID; + worker.invoke(&GeometryTileWorker::setShowCollisionBoxes, showCollisionBoxes, correlationID); + } +} + +void GeometryTile::onLayout(LayoutResult result, const uint64_t resultCorrelationID) { + // Don't mark ourselves loaded or renderable until the first successful placement + // TODO: Ideally we'd render this tile without symbols as long as this tile wasn't + // replacing a tile at a different zoom that _did_ have symbols. + (void)resultCorrelationID; nonSymbolBuckets = std::move(result.nonSymbolBuckets); featureIndex = std::move(result.featureIndex); data = std::move(result.tileData); - collisionTile.reset(); observer->onTileChanged(*this); } -void GeometryTile::onPlacement(PlacementResult result) { +void GeometryTile::onPlacement(PlacementResult result, const uint64_t resultCorrelationID) { loaded = true; renderable = true; - if (result.correlationID == correlationID) { + if (resultCorrelationID == correlationID) { pending = false; } symbolBuckets = std::move(result.symbolBuckets); - collisionTile = std::move(result.collisionTile); if (result.glyphAtlasImage) { glyphAtlasImage = std::move(*result.glyphAtlasImage); } if (result.iconAtlasImage) { iconAtlasImage = std::move(*result.iconAtlasImage); } + observer->onTileChanged(*this); } -void GeometryTile::onError(std::exception_ptr err) { +void GeometryTile::onError(std::exception_ptr err, const uint64_t resultCorrelationID) { loaded = true; - pending = false; - renderable = false; + if (resultCorrelationID == correlationID) { + pending = false; + } observer->onTileError(*this, err); } @@ -161,27 +168,27 @@ void GeometryTile::getGlyphs(GlyphDependencies glyphDependencies) { glyphManager.getGlyphs(*this, std::move(glyphDependencies)); } -void GeometryTile::onImagesAvailable(ImageMap images) { - worker.invoke(&GeometryTileWorker::onImagesAvailable, std::move(images)); +void GeometryTile::onImagesAvailable(ImageMap images, uint64_t imageCorrelationID) { + worker.invoke(&GeometryTileWorker::onImagesAvailable, std::move(images), imageCorrelationID); } -void GeometryTile::getImages(ImageDependencies imageDependencies) { - imageManager.getImages(*this, std::move(imageDependencies)); +void GeometryTile::getImages(ImageRequestPair pair) { + imageManager.getImages(*this, std::move(pair)); } void GeometryTile::upload(gl::Context& context) { - auto upload = [&] (Bucket& bucket) { + auto uploadFn = [&] (Bucket& bucket) { if (bucket.needsUpload()) { bucket.upload(context); } }; for (auto& entry : nonSymbolBuckets) { - upload(*entry.second); + uploadFn(*entry.second); } for (auto& entry : symbolBuckets) { - upload(*entry.second); + uploadFn(*entry.second); } if (glyphAtlasImage) { @@ -210,11 +217,21 @@ void GeometryTile::queryRenderedFeatures( std::unordered_map<std::string, std::vector<Feature>>& result, const GeometryCoordinates& queryGeometry, const TransformState& transformState, - const RenderStyle& style, - const RenderedQueryOptions& options) { + const std::vector<const RenderLayer*>& layers, + const RenderedQueryOptions& options, + const CollisionIndex& collisionIndex) { 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(), @@ -222,10 +239,11 @@ void GeometryTile::queryRenderedFeatures( std::pow(2, transformState.getZoom() - id.overscaledZ), options, *data, - id.canonical, - style, - collisionTile.get(), - *this); + id.toUnwrapped(), + sourceID, + layers, + collisionIndex, + additionalRadius); } void GeometryTile::querySourceFeatures( @@ -264,4 +282,37 @@ void GeometryTile::querySourceFeatures( } } +void GeometryTile::resetCrossTileIDs() { + for (auto& bucket : symbolBuckets) { + auto symbolBucket = dynamic_cast<SymbolBucket*>(bucket.second.get()); + if (symbolBucket && symbolBucket->bucketInstanceId) { + symbolBucket->bucketInstanceId = 0; + for (auto& symbolInstance : symbolBucket->symbolInstances) { + symbolInstance.crossTileID = 0; + } + } + } +} + +bool GeometryTile::holdForFade() const { + return mode == MapMode::Continuous && + (fadeState == FadeState::NeedsFirstPlacement || fadeState == FadeState::NeedsSecondPlacement); +} + +void GeometryTile::markRenderedIdeal() { + fadeState = FadeState::Loaded; +} +void GeometryTile::markRenderedPreviously() { + if (fadeState == FadeState::Loaded) { + fadeState = FadeState::NeedsFirstPlacement; + } +} +void GeometryTile::performedFadePlacement() { + if (fadeState == FadeState::NeedsFirstPlacement) { + fadeState = FadeState::NeedsSecondPlacement; + } else if (fadeState == FadeState::NeedsSecondPlacement) { + fadeState = FadeState::CanRemove; + } +} + } // namespace mbgl |