Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[core] Use a separate atlas and store for annotation sprites
Browse files Browse the repository at this point in the history
Fixes #1488
  • Loading branch information
adam-mapbox authored and jfirebaugh committed Nov 26, 2015
1 parent db77a6f commit c2f8304
Show file tree
Hide file tree
Showing 14 changed files with 69 additions and 27 deletions.
17 changes: 16 additions & 1 deletion src/mbgl/annotation/annotation_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ namespace mbgl {
const std::string AnnotationManager::SourceID = "com.mapbox.annotations";
const std::string AnnotationManager::PointLayerID = "com.mapbox.annotations.points";

AnnotationManager::AnnotationManager() = default;
AnnotationManager::AnnotationManager(float pixelRatio)
: spriteStore(pixelRatio),
spriteAtlas(512, 512, pixelRatio, spriteStore) {
}

AnnotationManager::~AnnotationManager() = default;

AnnotationIDs
Expand Down Expand Up @@ -122,6 +126,7 @@ void AnnotationManager::updateStyle(Style& style) {
layer->sourceLayer = PointLayerID;
layer->layout.icon.image = std::string("{sprite}");
layer->layout.icon.allowOverlap = true;
layer->spriteAtlas = &spriteAtlas;

style.addLayer(std::move(layer));
}
Expand Down Expand Up @@ -152,4 +157,14 @@ void AnnotationManager::removeTileMonitor(AnnotationTileMonitor& monitor) {
monitors.erase(&monitor);
}

void AnnotationManager::setSprite(const std::string& name, std::shared_ptr<const SpriteImage> sprite) {
spriteStore.setSprite(name, sprite);
spriteAtlas.updateDirty();
}

double AnnotationManager::getTopOffsetPixelsForAnnotationSymbol(const std::string& name) {
auto sprite = spriteStore.getSprite(name);
return sprite ? -sprite->height / 2 : 0;
}

}
11 changes: 10 additions & 1 deletion src/mbgl/annotation/annotation_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/annotation/point_annotation_impl.hpp>
#include <mbgl/annotation/shape_annotation_impl.hpp>
#include <mbgl/sprite/sprite_store.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/noncopyable.hpp>

Expand All @@ -21,7 +23,7 @@ class Style;

class AnnotationManager : private util::noncopyable {
public:
AnnotationManager();
AnnotationManager(float pixelRatio);
~AnnotationManager();

AnnotationIDs addPointAnnotations(const std::vector<PointAnnotation>&, const uint8_t maxZoom);
Expand All @@ -31,6 +33,10 @@ class AnnotationManager : private util::noncopyable {
AnnotationIDs getPointAnnotationsInBounds(const LatLngBounds&) const;
LatLngBounds getBoundsForAnnotations(const AnnotationIDs&) const;

void setSprite(const std::string& name, std::shared_ptr<const SpriteImage>);
double getTopOffsetPixelsForAnnotationSymbol(const std::string& name);
SpriteAtlas& getSpriteAtlas() { return spriteAtlas; }

void updateStyle(Style&);

void addTileMonitor(AnnotationTileMonitor&);
Expand All @@ -48,6 +54,9 @@ class AnnotationManager : private util::noncopyable {
ShapeAnnotationImpl::Map shapeAnnotations;
std::vector<std::string> obsoleteShapeAnnotationLayers;
std::set<AnnotationTileMonitor*> monitors;

SpriteStore spriteStore;
SpriteAtlas spriteAtlas;
};

}
Expand Down
3 changes: 2 additions & 1 deletion src/mbgl/layer/symbol_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ std::unique_ptr<StyleLayer> SymbolLayer::clone() const {
result->copy(*this);
result->layout = layout;
result->paint = paint;
result->spriteAtlas = spriteAtlas;
return std::move(result);
}

Expand Down Expand Up @@ -178,7 +179,7 @@ std::unique_ptr<Bucket> SymbolLayer::createBucket(StyleBucketParameters& paramet
// needed by this tile.
if (!parameters.partialParse) {
bucket->addFeatures(parameters.tileUID,
parameters.spriteAtlas,
*spriteAtlas,
parameters.glyphAtlas,
parameters.glyphStore,
parameters.collisionTile);
Expand Down
4 changes: 4 additions & 0 deletions src/mbgl/layer/symbol_layer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

namespace mbgl {

class SpriteAtlas;

class SymbolLayoutProperties {
public:
LayoutProperty<PlacementType> placement = PlacementType::Point;
Expand Down Expand Up @@ -94,6 +96,8 @@ class SymbolLayer : public StyleLayer {

SymbolLayoutProperties layout;
SymbolPaintProperties paint;

SpriteAtlas* spriteAtlas;
};

}
Expand Down
19 changes: 4 additions & 15 deletions src/mbgl/map/map_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ bool MapContext::renderSync(const TransformState& state, const FrameData& frame)
glObjectStore.performCleanup();

if (!painter) painter = std::make_unique<Painter>(data, transformState);
painter->render(*style, frame);
painter->render(*style, frame, data.getAnnotationManager()->getSpriteAtlas());

if (data.mode == MapMode::Still) {
callback(nullptr, std::move(view.readStillImage()));
Expand All @@ -270,12 +270,7 @@ bool MapContext::isLoaded() const {

double MapContext::getTopOffsetPixelsForAnnotationSymbol(const std::string& symbol) {
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
auto sprite = style->spriteStore->getSprite(symbol);
if (sprite) {
return -sprite->height / 2;
} else {
return 0;
}
return data.getAnnotationManager()->getTopOffsetPixelsForAnnotationSymbol(symbol);
}

void MapContext::setSourceTileCacheSize(size_t size) {
Expand All @@ -300,14 +295,8 @@ void MapContext::onLowMemory() {
}

void MapContext::setSprite(const std::string& name, std::shared_ptr<const SpriteImage> sprite) {
if (!style) {
Log::Info(Event::Sprite, "Ignoring sprite without stylesheet");
return;
}

style->spriteStore->setSprite(name, sprite);

style->spriteAtlas->updateDirty();
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
data.getAnnotationManager()->setSprite(name, sprite);
}

void MapContext::onTileDataChanged() {
Expand Down
1 change: 1 addition & 0 deletions src/mbgl/map/map_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class MapData {
: mode(mode_)
, contextMode(contextMode_)
, pixelRatio(pixelRatio_)
, annotationManager(pixelRatio)
, animationTime(Duration::zero())
, defaultFadeDuration(mode_ == MapMode::Continuous ? std::chrono::milliseconds(300) : Duration::zero())
, defaultTransitionDuration(Duration::zero())
Expand Down
4 changes: 3 additions & 1 deletion src/mbgl/map/tile_worker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ TileParseResult TileWorker::parsePendingLayers() {
if (layer.type == StyleLayerType::Symbol) {
auto symbolBucket = dynamic_cast<SymbolBucket*>(bucket.get());
if (!symbolBucket->needsDependencies(*style.glyphStore, *style.spriteStore)) {
symbolBucket->addFeatures(reinterpret_cast<uintptr_t>(this), *style.spriteAtlas,
const SymbolLayer* symbolLayer = dynamic_cast<const SymbolLayer*>(&layer);
symbolBucket->addFeatures(reinterpret_cast<uintptr_t>(this),
*symbolLayer->spriteAtlas,
*style.glyphAtlas, *style.glyphStore, *collisionTile);
insertBucket(layer.bucketName(), std::move(bucket));
pending.erase(it++);
Expand Down
3 changes: 2 additions & 1 deletion src/mbgl/renderer/painter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ void Painter::prepareTile(const Tile& tile) {
config.stencilFunc = { GL_EQUAL, ref, mask };
}

void Painter::render(const Style& style, const FrameData& frame_) {
void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& annotationSpriteAtlas) {
frame = frame_;

glyphAtlas = style.glyphAtlas.get();
Expand Down Expand Up @@ -158,6 +158,7 @@ void Painter::render(const Style& style, const FrameData& frame_) {
spriteAtlas->upload();
lineAtlas->upload();
glyphAtlas->upload();
annotationSpriteAtlas.upload();

for (const auto& item : order) {
if (item.bucket && item.bucket->needsUpload()) {
Expand Down
3 changes: 2 additions & 1 deletion src/mbgl/renderer/painter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ class Painter : private util::noncopyable {
void changeMatrix();

void render(const Style& style,
const FrameData& frame);
const FrameData& frame,
SpriteAtlas& annotationSpriteAtlas);

// Renders debug information for a tile.
void renderTileDebug(const Tile& tile);
Expand Down
5 changes: 3 additions & 2 deletions src/mbgl/renderer/painter_symbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,8 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const
const float fontSize = properties.icon.size;
const float fontScale = fontSize / 1.0f;

spriteAtlas->bind(state.isChanging() || layout.placement == PlacementType::Line
SpriteAtlas* activeSpriteAtlas = layer.spriteAtlas;
activeSpriteAtlas->bind(state.isChanging() || layout.placement == PlacementType::Line
|| angleOffset != 0 || fontScale != 1 || sdf || state.getPitch() != 0);

if (sdf) {
Expand All @@ -202,7 +203,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const
layout.icon,
properties.icon,
1.0f,
{{ float(spriteAtlas->getWidth()) / 4.0f, float(spriteAtlas->getHeight()) / 4.0f }},
{{ float(activeSpriteAtlas->getWidth()) / 4.0f, float(activeSpriteAtlas->getHeight()) / 4.0f }},
*sdfIconShader,
&SymbolBucket::drawIcons);
} else {
Expand Down
11 changes: 9 additions & 2 deletions src/mbgl/sprite/sprite_atlas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ SpriteAtlas::SpriteAtlas(dimension width_, dimension height_, float pixelRatio_,
pixelRatio(pixelRatio_),
store(store_),
bin(width_, height_),
data(std::make_unique<uint32_t[]>(pixelWidth * pixelHeight)),
dirty(true) {
std::fill(data.get(), data.get() + pixelWidth * pixelHeight, 0);
}

Rect<SpriteAtlas::dimension> SpriteAtlas::allocateImage(const size_t pixel_width, const size_t pixel_height) {
Expand Down Expand Up @@ -103,6 +101,11 @@ SpriteAtlasPosition SpriteAtlas::getPosition(const std::string& name, bool repea
}

void SpriteAtlas::copy(const Holder& holder, const bool wrap) {
if (!data) {
data = std::make_unique<uint32_t[]>(pixelWidth * pixelHeight);
std::fill(data.get(), data.get() + pixelWidth * pixelHeight, 0);
}

const uint32_t *srcData = reinterpret_cast<const uint32_t *>(holder.texture->data.data());
if (!srcData) return;
const vec2<uint32_t> srcSize { holder.texture->pixelWidth, holder.texture->pixelHeight };
Expand Down Expand Up @@ -189,6 +192,10 @@ void SpriteAtlas::updateDirty() {
}

void SpriteAtlas::bind(bool linear) {
if (!data) {
return; // Empty atlas
}

if (!texture) {
MBGL_CHECK_ERROR(glGenTextures(1, &texture));
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture));
Expand Down
4 changes: 3 additions & 1 deletion src/mbgl/sprite/sprite_atlas.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ class SpriteAtlas : public util::noncopyable {
inline dimension getTextureWidth() const { return pixelWidth; }
inline dimension getTextureHeight() const { return pixelHeight; }
inline float getPixelRatio() const { return pixelRatio; }

// Only for use in tests.
inline const uint32_t* getData() const { return data.get(); }

private:
Expand All @@ -90,7 +92,7 @@ class SpriteAtlas : public util::noncopyable {
BinPack<dimension> bin;
std::map<Key, Holder> images;
std::set<std::string> uninitialized;
const std::unique_ptr<uint32_t[]> data;
std::unique_ptr<uint32_t[]> data;
std::atomic<bool> dirty;
bool fullUploadRequired = true;
GLuint texture = 0;
Expand Down
7 changes: 7 additions & 0 deletions src/mbgl/style/style.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <mbgl/map/map_data.hpp>
#include <mbgl/map/source.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/layer/symbol_layer.hpp>
#include <mbgl/sprite/sprite_store.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/style/style_layer.hpp>
Expand Down Expand Up @@ -88,6 +89,12 @@ StyleLayer* Style::getLayer(const std::string& id) const {
}

void Style::addLayer(util::ptr<StyleLayer> layer) {
if (SymbolLayer* symbolLayer = dynamic_cast<SymbolLayer*>(layer.get())) {
if (!symbolLayer->spriteAtlas) {
symbolLayer->spriteAtlas = spriteAtlas.get();
}
}

layers.emplace_back(std::move(layer));
}

Expand Down
4 changes: 3 additions & 1 deletion test/sprite/sprite_atlas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ TEST(Sprite, SpriteAtlas) {
EXPECT_EQ(112, atlas.getTextureHeight());

// Image hasn't been created yet.
EXPECT_TRUE(atlas.getData());
EXPECT_FALSE(atlas.getData());

auto metro = atlas.getImage("metro", false);
EXPECT_EQ(0, metro.pos.x);
Expand All @@ -42,6 +42,8 @@ TEST(Sprite, SpriteAtlas) {
EXPECT_EQ(18, metro.texture->pixelHeight);
EXPECT_EQ(1.0f, metro.texture->pixelRatio);

EXPECT_TRUE(atlas.getData());

auto pos = atlas.getPosition("metro", false);
EXPECT_DOUBLE_EQ(20, pos.size[0]);
EXPECT_DOUBLE_EQ(20, pos.size[1]);
Expand Down

0 comments on commit c2f8304

Please sign in to comment.