diff options
author | Chris Loer <chris.loer@gmail.com> | 2017-03-31 14:53:18 -0700 |
---|---|---|
committer | Chris Loer <chris.loer@mapbox.com> | 2017-04-04 11:33:12 -0700 |
commit | 5cdf838a387cae446dba500ac49a1c5524bf7949 (patch) | |
tree | 3b438034a7842c36a7804096785fca1a6ad6fa80 /src/mbgl/tile | |
parent | 64beba3accb0f2088b2e01fad710f915c81d99c7 (diff) | |
download | qtlocation-mapboxgl-5cdf838a387cae446dba500ac49a1c5524bf7949.tar.gz |
[core] De-mutex GlyphAtlas and SpriteAtlas
- Expose glyph and icon information to workers via message interface.
- Glyph/SpriteAtlas track which tiles have outstanding requests
and send messages to them when glyphs/icons become available.
- Remove obsolete "updateSymbolDependentTiles" pathway
- Symbol preparation for a tile now depends on all glyphs becoming
available before it can start.
- Start tracking individual icons needed for a tile, although we don't
do anything with the information yet.
- Introduce typedef for GlyphID
Diffstat (limited to 'src/mbgl/tile')
-rw-r--r-- | src/mbgl/tile/geometry_tile.cpp | 39 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile.hpp | 15 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile_worker.cpp | 133 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile_worker.hpp | 21 | ||||
-rw-r--r-- | src/mbgl/tile/tile.hpp | 1 |
5 files changed, 158 insertions, 51 deletions
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 5ccc037ce0..4e67144082 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -18,6 +18,8 @@ #include <mbgl/style/query.hpp> #include <mbgl/util/logging.hpp> +#include <iostream> + namespace mbgl { using namespace style; @@ -32,12 +34,16 @@ GeometryTile::GeometryTile(const OverscaledTileID& id_, worker(parameters.workerScheduler, ActorRef<GeometryTile>(*this, mailbox), id_, - *parameters.style.glyphAtlas, obsolete, - parameters.mode) { + parameters.mode), + glyphAtlas(*parameters.style.glyphAtlas) { } GeometryTile::~GeometryTile() { + glyphAtlas.removeGlyphs(*this); + for (auto spriteAtlas : pendingSpriteAtlases) { + spriteAtlas->removeRequestor(*this); + } cancel(); } @@ -77,10 +83,6 @@ void GeometryTile::setPlacementConfig(const PlacementConfig& desiredConfig) { worker.invoke(&GeometryTileWorker::setPlacementConfig, desiredConfig, correlationID); } -void GeometryTile::symbolDependenciesChanged() { - worker.invoke(&GeometryTileWorker::symbolDependenciesChanged); -} - void GeometryTile::redoLayout() { // Mark the tile as pending again if it was complete before to prevent signaling a complete // state despite pending parse operations. @@ -130,6 +132,31 @@ void GeometryTile::onError(std::exception_ptr err) { availableData = DataAvailability::All; observer->onTileError(*this, err); } + +void GeometryTile::onGlyphsAvailable(GlyphPositionMap glyphPositions, GlyphRangeSet loadedRanges) { + worker.invoke(&GeometryTileWorker::onGlyphsAvailable, std::move(glyphPositions), std::move(loadedRanges)); +} + +void GeometryTile::getGlyphs(GlyphDependencies glyphDependencies) { + glyphAtlas.getGlyphs(*this, std::move(glyphDependencies)); +} + +void GeometryTile::onIconsAvailable(SpriteAtlas* spriteAtlas, IconMap icons) { + iconAtlasMap[(uintptr_t)spriteAtlas] = icons; + pendingSpriteAtlases.erase(spriteAtlas); + if (pendingSpriteAtlases.empty()) { + worker.invoke(&GeometryTileWorker::onIconsAvailable, std::move(iconAtlasMap)); + } +} + +// TODO: If there's any value to be gained by it, we can narrow our request to just the sprites +// we need, but SpriteAtlases are just "loaded" or "not loaded" +void GeometryTile::getIcons(IconDependencyMap iconDependencyMap) { + for (auto dependency : iconDependencyMap) { + pendingSpriteAtlases.insert(dependency.first); + dependency.first->getIcons(*this); + } +} Bucket* GeometryTile::getBucket(const Layer& layer) { const auto& buckets = layer.is<SymbolLayer>() ? symbolBuckets : nonSymbolBuckets; diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp index cabe193467..f057e21507 100644 --- a/src/mbgl/tile/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp @@ -1,7 +1,9 @@ #pragma once +#include <mbgl/sprite/sprite_atlas.hpp> #include <mbgl/tile/tile.hpp> #include <mbgl/tile/geometry_tile_worker.hpp> +#include <mbgl/text/glyph_atlas.hpp> #include <mbgl/text/placement_config.hpp> #include <mbgl/util/feature.hpp> #include <mbgl/actor/actor.hpp> @@ -24,7 +26,7 @@ class UpdateParameters; class SourceQueryOptions; } // namespace style -class GeometryTile : public Tile { +class GeometryTile : public Tile, public GlyphRequestor, IconRequestor { public: GeometryTile(const OverscaledTileID&, std::string sourceID, @@ -36,8 +38,13 @@ public: void setData(std::unique_ptr<const GeometryTileData>); void setPlacementConfig(const PlacementConfig&) override; - void symbolDependenciesChanged() override; void redoLayout() override; + + void onGlyphsAvailable(GlyphPositionMap, GlyphRangeSet) override; + void onIconsAvailable(SpriteAtlas*, IconMap) override; + + void getGlyphs(GlyphDependencies); + void getIcons(IconDependencyMap); Bucket* getBucket(const style::Layer&) override; @@ -87,6 +94,10 @@ private: std::shared_ptr<Mailbox> mailbox; Actor<GeometryTileWorker> worker; + GlyphAtlas& glyphAtlas; + std::set<SpriteAtlas*> pendingSpriteAtlases; + IconAtlasMap iconAtlasMap; + uint64_t correlationID = 0; optional<PlacementConfig> requestedConfig; diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index b1fd7a852e..d1d4c9e9b8 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -2,8 +2,8 @@ #include <mbgl/tile/geometry_tile_data.hpp> #include <mbgl/tile/geometry_tile.hpp> #include <mbgl/text/collision_tile.hpp> -#include <mbgl/text/glyph_atlas.hpp> #include <mbgl/layout/symbol_layout.hpp> +#include <mbgl/sprite/sprite_atlas.hpp> #include <mbgl/style/bucket_parameters.hpp> #include <mbgl/style/group_by_layout.hpp> #include <mbgl/style/filter.hpp> @@ -25,19 +25,16 @@ using namespace style; GeometryTileWorker::GeometryTileWorker(ActorRef<GeometryTileWorker> self_, ActorRef<GeometryTile> parent_, OverscaledTileID id_, - GlyphAtlas& glyphAtlas_, const std::atomic<bool>& obsolete_, const MapMode mode_) : self(std::move(self_)), parent(std::move(parent_)), id(std::move(id_)), - glyphAtlas(glyphAtlas_), obsolete(obsolete_), mode(mode_) { } GeometryTileWorker::~GeometryTileWorker() { - glyphAtlas.removeGlyphs(reinterpret_cast<uintptr_t>(this)); } /* @@ -147,14 +144,14 @@ void GeometryTileWorker::symbolDependenciesChanged() { try { switch (state) { case Idle: - if (hasPendingSymbolDependencies()) { + if (hasPendingSymbolLayouts()) { attemptPlacement(); coalesce(); } break; case Coalescing: - if (hasPendingSymbolDependencies()) { + if (hasPendingSymbolLayouts()) { state = NeedPlacement; } break; @@ -199,6 +196,71 @@ void GeometryTileWorker::coalesce() { self.invoke(&GeometryTileWorker::coalesced); } + +void GeometryTileWorker::onGlyphsAvailable(GlyphPositionMap newGlyphPositions, GlyphRangeSet loadedRanges) { + GlyphDependencies loadedGlyphs; + for (auto& pendingFontGlyphs : pendingGlyphDependencies) { + auto newFontGlyphs = newGlyphPositions.find(pendingFontGlyphs.first); + for (auto glyphID : pendingFontGlyphs.second) { + if (newFontGlyphs != newGlyphPositions.end()) { + auto newFontGlyph = newFontGlyphs->second.find(glyphID); + if (newFontGlyph != newFontGlyphs->second.end()) { + glyphPositions[pendingFontGlyphs.first].emplace(glyphID, newFontGlyph->second); + } + } + if (loadedRanges.find(getGlyphRange(glyphID)) != loadedRanges.end()) { + // Erase the glyph from our pending font set as long as its range is loaded + // If the glyph itself is missing, that means we can't get a glyph for + // this fontstack, and we go ahead and render with missing glyphs + loadedGlyphs[pendingFontGlyphs.first].insert(glyphID); + } + } + } + + for (auto& loadedFont : loadedGlyphs) { + for (auto loadedGlyph : loadedFont.second) { + pendingGlyphDependencies[loadedFont.first].erase(loadedGlyph); + } + } + symbolDependenciesChanged(); +} + +void GeometryTileWorker::onIconsAvailable(IconAtlasMap newIcons) { + for (auto& atlasIcons : newIcons) { + auto pendingAtlasIcons = pendingIconDependencies.find((SpriteAtlas*)atlasIcons.first); + if (pendingAtlasIcons != pendingIconDependencies.end()) { + icons[atlasIcons.first] = std::move(newIcons[atlasIcons.first]); + pendingIconDependencies.erase((SpriteAtlas*)atlasIcons.first); + } + } + symbolDependenciesChanged(); +} + +void GeometryTileWorker::requestNewGlyphs(const GlyphDependencies& glyphDependencies) { + for (auto& fontDependencies : glyphDependencies) { + auto fontGlyphs = glyphPositions.find(fontDependencies.first); + for (auto glyphID : fontDependencies.second) { + if (fontGlyphs == glyphPositions.end() || fontGlyphs->second.find(glyphID) == fontGlyphs->second.end()) { + pendingGlyphDependencies[fontDependencies.first].insert(glyphID); + } + } + } + if (!pendingGlyphDependencies.empty()) { + parent.invoke(&GeometryTile::getGlyphs, pendingGlyphDependencies); + } +} + +void GeometryTileWorker::requestNewIcons(const IconDependencyMap &iconDependencies) { + for (auto& atlasDependency : iconDependencies) { + if (icons.find((uintptr_t)atlasDependency.first) == icons.end()) { + pendingIconDependencies[atlasDependency.first] = IconDependencies(); + } + } + if (!pendingIconDependencies.empty()) { + parent.invoke(&GeometryTile::getIcons, pendingIconDependencies); + } +} + void GeometryTileWorker::redoLayout() { if (!data || !layers) { return; @@ -215,6 +277,9 @@ void GeometryTileWorker::redoLayout() { std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets; auto featureIndex = std::make_unique<FeatureIndex>(); BucketParameters parameters { id, mode }; + + GlyphDependencies glyphDependencies; + IconDependencyMap iconDependencyMap; std::vector<std::vector<const Layer*>> groups = groupByLayout(*layers); for (auto& group : groups) { @@ -242,7 +307,7 @@ void GeometryTileWorker::redoLayout() { if (leader.is<SymbolLayer>()) { symbolLayoutMap.emplace(leader.getID(), - leader.as<SymbolLayer>()->impl->createLayout(parameters, group, *geometryLayer)); + leader.as<SymbolLayer>()->impl->createLayout(parameters, group, *geometryLayer, glyphDependencies, iconDependencyMap)); } else { const Filter& filter = leader.baseImpl->filter; const std::string& sourceLayerID = leader.baseImpl->sourceLayer; @@ -276,6 +341,9 @@ void GeometryTileWorker::redoLayout() { symbolLayouts.push_back(std::move(it->second)); } } + + requestNewGlyphs(glyphDependencies); + requestNewIcons(iconDependencyMap); parent.invoke(&GeometryTile::onLayout, GeometryTile::LayoutResult { std::move(buckets), @@ -287,46 +355,31 @@ void GeometryTileWorker::redoLayout() { attemptPlacement(); } -bool GeometryTileWorker::hasPendingSymbolDependencies() const { - bool result = false; - +bool GeometryTileWorker::hasPendingSymbolLayouts() const { for (const auto& symbolLayout : symbolLayouts) { if (symbolLayout->state == SymbolLayout::Pending) { - result = true; + return true; } } - return result; + return false; } -void GeometryTileWorker::attemptPlacement() { - if (!data || !layers || !placementConfig) { - return; - } - - bool canPlace = true; - - // Prepare as many SymbolLayouts as possible. - for (auto& symbolLayout : symbolLayouts) { - if (obsolete) { - return; - } - - if (symbolLayout->state == SymbolLayout::Pending) { - if (symbolLayout->canPrepare(glyphAtlas)) { - symbolLayout->state = SymbolLayout::Prepared; - symbolLayout->prepare(reinterpret_cast<uintptr_t>(this), - glyphAtlas); - } else { - canPlace = false; - } +bool GeometryTileWorker::hasPendingSymbolDependencies() const { + for (auto& glyphDependency : pendingGlyphDependencies) { + if (!glyphDependency.second.empty()) { + return true; } } + return !pendingIconDependencies.empty(); +} - if (!canPlace) { - return; // We'll be notified (via `setPlacementConfig`) when it's time to try again. - } +void GeometryTileWorker::attemptPlacement() { + if (!data || !layers || !placementConfig || hasPendingSymbolDependencies()) { + return; + } + auto collisionTile = std::make_unique<CollisionTile>(*placementConfig); std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets; @@ -334,8 +387,12 @@ void GeometryTileWorker::attemptPlacement() { if (obsolete) { return; } - - symbolLayout->state = SymbolLayout::Placed; + + if (symbolLayout->state == SymbolLayout::Pending) { + symbolLayout->prepare(glyphPositions,icons); + symbolLayout->state = SymbolLayout::Placed; + } + if (!symbolLayout->hasSymbolInstances()) { continue; } diff --git a/src/mbgl/tile/geometry_tile_worker.hpp b/src/mbgl/tile/geometry_tile_worker.hpp index 91bf81a697..39f4411e23 100644 --- a/src/mbgl/tile/geometry_tile_worker.hpp +++ b/src/mbgl/tile/geometry_tile_worker.hpp @@ -2,6 +2,8 @@ #include <mbgl/map/mode.hpp> #include <mbgl/tile/tile_id.hpp> +#include <mbgl/sprite/sprite_atlas.hpp> +#include <mbgl/text/glyph.hpp> #include <mbgl/text/placement_config.hpp> #include <mbgl/actor/actor_ref.hpp> #include <mbgl/util/optional.hpp> @@ -25,7 +27,6 @@ public: GeometryTileWorker(ActorRef<GeometryTileWorker> self, ActorRef<GeometryTile> parent, OverscaledTileID, - GlyphAtlas&, const std::atomic<bool>&, const MapMode); ~GeometryTileWorker(); @@ -33,20 +34,28 @@ public: void setLayers(std::vector<std::unique_ptr<style::Layer>>, uint64_t correlationID); void setData(std::unique_ptr<const GeometryTileData>, uint64_t correlationID); void setPlacementConfig(PlacementConfig, uint64_t correlationID); - void symbolDependenciesChanged(); + + void onGlyphsAvailable(GlyphPositionMap glyphs, GlyphRangeSet loadedRanges); + void onIconsAvailable(IconAtlasMap icons); private: - void coalesce(); void coalesced(); void redoLayout(); void attemptPlacement(); + + void coalesce(); + + void requestNewGlyphs(const GlyphDependencies&); + void requestNewIcons(const IconDependencyMap&); + + void symbolDependenciesChanged(); bool hasPendingSymbolDependencies() const; + bool hasPendingSymbolLayouts() const; ActorRef<GeometryTileWorker> self; ActorRef<GeometryTile> parent; const OverscaledTileID id; - GlyphAtlas& glyphAtlas; const std::atomic<bool>& obsolete; const MapMode mode; @@ -66,6 +75,10 @@ private: optional<PlacementConfig> placementConfig; std::vector<std::unique_ptr<SymbolLayout>> symbolLayouts; + GlyphDependencies pendingGlyphDependencies; + IconDependencyMap pendingIconDependencies; + GlyphPositionMap glyphPositions; + IconAtlasMap icons; }; } // namespace mbgl diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp index 613b15f36c..a5f574b567 100644 --- a/src/mbgl/tile/tile.hpp +++ b/src/mbgl/tile/tile.hpp @@ -50,7 +50,6 @@ public: virtual Bucket* getBucket(const style::Layer&) = 0; virtual void setPlacementConfig(const PlacementConfig&) {} - virtual void symbolDependenciesChanged() {}; virtual void redoLayout() {} virtual void queryRenderedFeatures( |