summaryrefslogtreecommitdiff
path: root/src/mbgl/tile
diff options
context:
space:
mode:
authorChris Loer <chris.loer@gmail.com>2017-03-31 14:53:18 -0700
committerChris Loer <chris.loer@mapbox.com>2017-04-04 11:33:12 -0700
commit5cdf838a387cae446dba500ac49a1c5524bf7949 (patch)
tree3b438034a7842c36a7804096785fca1a6ad6fa80 /src/mbgl/tile
parent64beba3accb0f2088b2e01fad710f915c81d99c7 (diff)
downloadqtlocation-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.cpp39
-rw-r--r--src/mbgl/tile/geometry_tile.hpp15
-rw-r--r--src/mbgl/tile/geometry_tile_worker.cpp133
-rw-r--r--src/mbgl/tile/geometry_tile_worker.hpp21
-rw-r--r--src/mbgl/tile/tile.hpp1
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(