[core] Tweak handling of annotation special case SpriteAtlas

* Simplify SymbolLayout; it never needs to care about more than one SpriteAtlas.
* Move the reference from SymbolLayer::Impl to SymbolBucket. This is a prerequisite for making layer Impls immutable.
This commit is contained in:
John Firebaugh
2017-04-26 12:42:17 -07:00
parent ea0e45b401
commit 1c42daa152
19 changed files with 78 additions and 98 deletions

View File

@@ -175,8 +175,6 @@ void AnnotationManager::updateStyle(Style& style) {
layer->setIconAllowOverlap(true);
layer->setIconIgnorePlacement(true);
layer->impl->spriteAtlas = &spriteAtlas;
style.addLayer(std::move(layer));
}

View File

@@ -75,6 +75,8 @@ private:
std::unordered_set<std::string> obsoleteShapeAnnotationLayers;
std::unordered_set<AnnotationTile*> tiles;
SpriteAtlas spriteAtlas;
friend class AnnotationTile;
};
} // namespace mbgl

View File

@@ -3,6 +3,7 @@
#include <mbgl/util/constants.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/style/update_parameters.hpp>
#include <mbgl/style/style.hpp>
#include <utility>
@@ -10,7 +11,9 @@ namespace mbgl {
AnnotationTile::AnnotationTile(const OverscaledTileID& overscaledTileID,
const style::UpdateParameters& parameters)
: GeometryTile(overscaledTileID, AnnotationManager::SourceID, parameters),
: GeometryTile(overscaledTileID, AnnotationManager::SourceID, parameters,
*parameters.style.glyphAtlas,
parameters.annotationManager.spriteAtlas),
annotationManager(parameters.annotationManager) {
annotationManager.addTile(*this);
}

View File

@@ -42,14 +42,12 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
const std::vector<const RenderLayer*>& layers,
const GeometryTileLayer& sourceLayer,
IconDependencies& iconDependencies,
uintptr_t _spriteAtlasMapIndex,
GlyphDependencies& glyphDependencies)
: sourceLayerName(sourceLayer.getName()),
bucketName(layers.at(0)->getID()),
overscaling(parameters.tileID.overscaleFactor()),
zoom(parameters.tileID.overscaledZ),
mode(parameters.mode),
spriteAtlasMapIndex(_spriteAtlasMapIndex),
tileSize(util::tileSize * overscaling),
tilePixelRatio(float(util::EXTENT) / tileSize),
textSize(layers.at(0)->as<RenderSymbolLayer>()->impl->layout.unevaluated.get<TextSize>()),
@@ -171,7 +169,7 @@ bool SymbolLayout::hasSymbolInstances() const {
return !symbolInstances.empty();
}
void SymbolLayout::prepare(const GlyphPositionMap& glyphs, const IconAtlasMap& iconMap) {
void SymbolLayout::prepare(const GlyphPositionMap& glyphs, const IconMap& icons) {
float horizontalAlign = 0.5;
float verticalAlign = 0.5;
@@ -259,21 +257,18 @@ void SymbolLayout::prepare(const GlyphPositionMap& glyphs, const IconAtlasMap& i
// if feature has icon, get sprite atlas position
if (feature.icon) {
auto icons = iconMap.find(spriteAtlasMapIndex);
if (icons != iconMap.end()) {
auto image = icons->second.find(*feature.icon);
if (image != icons->second.end()) {
shapedIcon = PositionedIcon::shapeIcon(image->second,
layout.evaluate<IconOffset>(zoom, feature),
layout.evaluate<IconRotate>(zoom, feature) * util::DEG2RAD);
if (image->second.sdf) {
sdfIcons = true;
}
if (image->second.relativePixelRatio != 1.0f) {
iconsNeedLinear = true;
} else if (layout.get<IconRotate>().constantOr(1) != 0) {
iconsNeedLinear = true;
}
auto image = icons.find(*feature.icon);
if (image != icons.end()) {
shapedIcon = PositionedIcon::shapeIcon(image->second,
layout.evaluate<IconOffset>(zoom, feature),
layout.evaluate<IconRotate>(zoom, feature) * util::DEG2RAD);
if (image->second.sdf) {
sdfIcons = true;
}
if (image->second.relativePixelRatio != 1.0f) {
iconsNeedLinear = true;
} else if (layout.get<IconRotate>().constantOr(1) != 0) {
iconsNeedLinear = true;
}
}
}

View File

@@ -31,10 +31,9 @@ public:
const std::vector<const RenderLayer*>&,
const GeometryTileLayer&,
IconDependencies&,
uintptr_t,
GlyphDependencies&);
void prepare(const GlyphPositionMap& glyphs, const IconAtlasMap& icons);
void prepare(const GlyphPositionMap& glyphs, const IconMap& icons);
std::unique_ptr<SymbolBucket> place(CollisionTile&);
@@ -81,8 +80,6 @@ private:
const MapMode mode;
style::SymbolLayoutProperties::PossiblyEvaluated layout;
uintptr_t spriteAtlasMapIndex; // Actually a pointer to the SpriteAtlas for this symbol's layer, but don't use it from worker threads!
const uint32_t tileSize;
const float tilePixelRatio;

View File

@@ -67,7 +67,7 @@ void Painter::renderSymbol(PaintParameters& parameters,
auto values = layer.iconPropertyValues(layout);
auto paintPropertyValues = layer.iconPaintProperties();
SpriteAtlas& atlas = *layer.impl->spriteAtlas;
SpriteAtlas& atlas = *bucket.spriteAtlas;
const bool iconScaled = layout.get<IconSize>().constantOr(1.0) != 1.0 ||
frame.pixelRatio != atlas.getPixelRatio() ||
bucket.iconsNeedLinear;

View File

@@ -26,12 +26,11 @@ std::unique_ptr<SymbolLayout> RenderSymbolLayer::createLayout(const BucketParame
const std::vector<const RenderLayer*>& group,
const GeometryTileLayer& layer,
GlyphDependencies& glyphDependencies,
IconDependencyMap& iconDependencyMap) const {
IconDependencies& iconDependencies) const {
return std::make_unique<SymbolLayout>(parameters,
group,
layer,
iconDependencyMap[impl->spriteAtlas],
(uintptr_t) impl->spriteAtlas,
iconDependencies,
glyphDependencies);
}

View File

@@ -77,7 +77,7 @@ public:
std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
std::unique_ptr<SymbolLayout> createLayout(const BucketParameters&, const std::vector<const RenderLayer*>&,
const GeometryTileLayer&, GlyphDependencies&, IconDependencyMap&) const;
const GeometryTileLayer&, GlyphDependencies&, IconDependencies&) const;
// Paint properties
style::SymbolPaintProperties::Unevaluated unevaluated;

View File

@@ -70,6 +70,8 @@ public:
optional<gl::VertexBuffer<CollisionBoxVertex>> vertexBuffer;
optional<gl::IndexBuffer<gl::Lines>> indexBuffer;
} collisionBox;
SpriteAtlas* spriteAtlas = nullptr;
};
} // namespace mbgl

View File

@@ -123,7 +123,7 @@ void SpriteAtlas::onParsed(Images&& result) {
}
observer->onSpriteLoaded();
for (auto requestor : requestors) {
requestor->onIconsAvailable(this, buildIconMap());
requestor->onIconsAvailable(buildIconMap());
}
requestors.clear();
}
@@ -202,7 +202,7 @@ const style::Image* SpriteAtlas::getImage(const std::string& id) const {
void SpriteAtlas::getIcons(IconRequestor& requestor) {
if (isLoaded()) {
requestor.onIconsAvailable(this, buildIconMap());
requestor.onIconsAvailable(buildIconMap());
} else {
requestors.insert(&requestor);
}

View File

@@ -38,16 +38,12 @@ public:
float height;
};
class SpriteAtlas;
typedef std::map<std::string,SpriteAtlasElement> IconMap;
typedef std::map<std::string, SpriteAtlasElement> IconMap;
typedef std::set<std::string> IconDependencies;
typedef std::map<uintptr_t,IconMap> IconAtlasMap;
typedef std::map<SpriteAtlas*,IconDependencies> IconDependencyMap;
class IconRequestor {
public:
virtual void onIconsAvailable(SpriteAtlas*, IconMap) = 0;
virtual void onIconsAvailable(IconMap) = 0;
};
class SpriteAtlas : public util::noncopyable {

View File

@@ -19,8 +19,6 @@ public:
SymbolLayoutProperties layout;
SymbolPaintProperties::Cascading cascading;
SpriteAtlas* spriteAtlas = nullptr;
};
} // namespace style

View File

@@ -223,12 +223,6 @@ Layer* Style::addLayer(std::unique_ptr<Layer> layer, optional<std::string> befor
throw std::runtime_error(std::string{"Layer "} + layer->getID() + " already exists");
}
if (SymbolLayer* symbolLayer = layer->as<SymbolLayer>()) {
if (!symbolLayer->impl->spriteAtlas) {
symbolLayer->impl->spriteAtlas = spriteAtlas.get();
}
}
if (CustomLayer* customLayer = layer->as<CustomLayer>()) {
customLayer->impl->initialize();
}

View File

@@ -1,6 +1,8 @@
#include <mbgl/tile/geojson_tile.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/style/query.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/update_parameters.hpp>
#include <mapbox/geojsonvt.hpp>
#include <supercluster.hpp>
@@ -83,7 +85,9 @@ public:
GeoJSONTile::GeoJSONTile(const OverscaledTileID& overscaledTileID,
std::string sourceID_,
const style::UpdateParameters& parameters)
: GeometryTile(overscaledTileID, sourceID_, parameters) {
: GeometryTile(overscaledTileID, sourceID_, parameters,
*parameters.style.glyphAtlas,
*parameters.style.spriteAtlas) {
}
void GeoJSONTile::updateData(const mapbox::geometry::feature_collection<int16_t>& features) {

View File

@@ -9,6 +9,7 @@
#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/storage/file_source.hpp>
#include <mbgl/geometry/feature_index.hpp>
@@ -28,7 +29,9 @@ using namespace style;
GeometryTile::GeometryTile(const OverscaledTileID& id_,
std::string sourceID_,
const style::UpdateParameters& parameters)
const style::UpdateParameters& parameters,
GlyphAtlas& glyphAtlas_,
SpriteAtlas& spriteAtlas_)
: Tile(id_),
sourceID(std::move(sourceID_)),
style(parameters.style),
@@ -38,14 +41,13 @@ GeometryTile::GeometryTile(const OverscaledTileID& id_,
id_,
obsolete,
parameters.mode),
glyphAtlas(*parameters.style.glyphAtlas) {
glyphAtlas(glyphAtlas_),
spriteAtlas(spriteAtlas_) {
}
GeometryTile::~GeometryTile() {
glyphAtlas.removeGlyphs(*this);
for (auto spriteAtlas : pendingSpriteAtlases) {
spriteAtlas->removeRequestor(*this);
}
spriteAtlas.removeRequestor(*this);
cancel();
}
@@ -125,6 +127,9 @@ void GeometryTile::onPlacement(PlacementResult result) {
pending = false;
}
symbolBuckets = std::move(result.symbolBuckets);
for (auto& entry : symbolBuckets) {
dynamic_cast<SymbolBucket*>(entry.second.get())->spriteAtlas = &spriteAtlas;
}
collisionTile = std::move(result.collisionTile);
observer->onTileChanged(*this);
}
@@ -144,21 +149,12 @@ 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));
}
void GeometryTile::onIconsAvailable(IconMap icons) {
worker.invoke(&GeometryTileWorker::onIconsAvailable, std::move(icons));
}
// 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);
}
void GeometryTile::getIcons(IconDependencies) {
spriteAtlas.getIcons(*this);
}
Bucket* GeometryTile::getBucket(const RenderLayer& layer) const {

View File

@@ -30,7 +30,9 @@ class GeometryTile : public Tile, public GlyphRequestor, IconRequestor {
public:
GeometryTile(const OverscaledTileID&,
std::string sourceID,
const style::UpdateParameters&);
const style::UpdateParameters&,
GlyphAtlas&,
SpriteAtlas&);
~GeometryTile() override;
@@ -41,10 +43,10 @@ public:
void redoLayout() override;
void onGlyphsAvailable(GlyphPositionMap) override;
void onIconsAvailable(SpriteAtlas*, IconMap) override;
void onIconsAvailable(IconMap) override;
void getGlyphs(GlyphDependencies);
void getIcons(IconDependencyMap);
void getIcons(IconDependencies);
Bucket* getBucket(const RenderLayer&) const override;
@@ -95,9 +97,8 @@ private:
Actor<GeometryTileWorker> worker;
GlyphAtlas& glyphAtlas;
std::set<SpriteAtlas*> pendingSpriteAtlases;
IconAtlasMap iconAtlasMap;
SpriteAtlas& spriteAtlas;
uint64_t correlationID = 0;
optional<PlacementConfig> requestedConfig;

View File

@@ -216,14 +216,9 @@ void GeometryTileWorker::onGlyphsAvailable(GlyphPositionMap newGlyphPositions) {
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);
}
}
void GeometryTileWorker::onIconsAvailable(IconMap newIcons) {
icons = std::move(newIcons);
pendingIconDependencies.clear();
symbolDependenciesChanged();
}
@@ -241,12 +236,8 @@ void GeometryTileWorker::requestNewGlyphs(const GlyphDependencies& glyphDependen
}
}
void GeometryTileWorker::requestNewIcons(const IconDependencyMap &iconDependencies) {
for (auto& atlasDependency : iconDependencies) {
if (icons.find((uintptr_t)atlasDependency.first) == icons.end()) {
pendingIconDependencies[atlasDependency.first] = IconDependencies();
}
}
void GeometryTileWorker::requestNewIcons(const IconDependencies& iconDependencies) {
pendingIconDependencies = iconDependencies;
if (!pendingIconDependencies.empty()) {
parent.invoke(&GeometryTile::getIcons, pendingIconDependencies);
}
@@ -290,9 +281,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;
IconDependencies iconDependencies;
// Create render layers and group by layout
std::vector<std::unique_ptr<RenderLayer>> renderLayers = toRenderLayers(*layers, id.overscaledZ);
@@ -323,7 +314,7 @@ void GeometryTileWorker::redoLayout() {
if (leader.is<RenderSymbolLayer>()) {
symbolLayoutMap.emplace(leader.getID(),
leader.as<RenderSymbolLayer>()->createLayout(parameters, group, *geometryLayer, glyphDependencies, iconDependencyMap));
leader.as<RenderSymbolLayer>()->createLayout(parameters, group, *geometryLayer, glyphDependencies, iconDependencies));
} else {
const Filter& filter = leader.baseImpl.filter;
const std::string& sourceLayerID = leader.baseImpl.sourceLayer;
@@ -357,9 +348,9 @@ void GeometryTileWorker::redoLayout() {
symbolLayouts.push_back(std::move(it->second));
}
}
requestNewGlyphs(glyphDependencies);
requestNewIcons(iconDependencyMap);
requestNewIcons(iconDependencies);
parent.invoke(&GeometryTile::onLayout, GeometryTile::LayoutResult {
std::move(buckets),
@@ -403,12 +394,12 @@ void GeometryTileWorker::attemptPlacement() {
if (obsolete) {
return;
}
if (symbolLayout->state == SymbolLayout::Pending) {
symbolLayout->prepare(glyphPositions,icons);
symbolLayout->prepare(glyphPositions, icons);
symbolLayout->state = SymbolLayout::Placed;
}
if (!symbolLayout->hasSymbolInstances()) {
continue;
}

View File

@@ -37,7 +37,7 @@ public:
void setPlacementConfig(PlacementConfig, uint64_t correlationID);
void onGlyphsAvailable(GlyphPositionMap glyphs);
void onIconsAvailable(IconAtlasMap icons);
void onIconsAvailable(IconMap icons);
private:
void coalesced();
@@ -47,7 +47,7 @@ private:
void coalesce();
void requestNewGlyphs(const GlyphDependencies&);
void requestNewIcons(const IconDependencyMap&);
void requestNewIcons(const IconDependencies&);
void symbolDependenciesChanged();
bool hasPendingSymbolDependencies() const;
@@ -77,9 +77,9 @@ private:
std::vector<std::unique_ptr<SymbolLayout>> symbolLayouts;
GlyphDependencies pendingGlyphDependencies;
IconDependencyMap pendingIconDependencies;
IconDependencies pendingIconDependencies;
GlyphPositionMap glyphPositions;
IconAtlasMap icons;
IconMap icons;
};
} // namespace mbgl

View File

@@ -1,6 +1,8 @@
#include <mbgl/tile/vector_tile.hpp>
#include <mbgl/tile/tile_loader_impl.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/update_parameters.hpp>
#include <protozero/pbf_reader.hpp>
@@ -83,7 +85,9 @@ VectorTile::VectorTile(const OverscaledTileID& id_,
std::string sourceID_,
const style::UpdateParameters& parameters,
const Tileset& tileset)
: GeometryTile(id_, sourceID_, parameters),
: GeometryTile(id_, sourceID_, parameters,
*parameters.style.glyphAtlas,
*parameters.style.spriteAtlas),
loader(*this, id_, parameters, tileset) {
}