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

Commit

Permalink
[core] Avoid unnecessary work when a symbol annotation is updated
Browse files Browse the repository at this point in the history
In particular, if only the geometry changes, don't cascade and recalculate the style.
  • Loading branch information
jfirebaugh committed Jun 17, 2016
1 parent e2f52a1 commit 2921127
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 28 deletions.
3 changes: 2 additions & 1 deletion include/mbgl/map/update.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ enum class Update : uint8_t {
RecalculateStyle = 1 << 3,
RenderStill = 1 << 4,
Repaint = 1 << 5,
Annotations = 1 << 6,
AnnotationStyle = 1 << 6,
AnnotationData = 1 << 7,
};

inline Update operator| (const Update& lhs, const Update& rhs) {
Expand Down
56 changes: 52 additions & 4 deletions src/mbgl/annotation/annotation_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ AnnotationID AnnotationManager::addAnnotation(const Annotation& annotation, cons
return id;
}

void AnnotationManager::updateAnnotation(const AnnotationID& id, const Annotation& annotation, const uint8_t maxZoom) {
removeAnnotation(id);
Annotation::visit(annotation, [&] (const auto& annotation_) {
this->add(id, annotation_, maxZoom);
Update AnnotationManager::updateAnnotation(const AnnotationID& id, const Annotation& annotation, const uint8_t maxZoom) {
return Annotation::visit(annotation, [&] (const auto& annotation_) {
return this->update(id, annotation_, maxZoom);
});
}

Expand Down Expand Up @@ -69,6 +68,53 @@ void AnnotationManager::add(const AnnotationID& id, const StyleSourcedAnnotation
std::make_unique<StyleSourcedAnnotationImpl>(id, annotation, maxZoom));
}

Update AnnotationManager::update(const AnnotationID& id, const SymbolAnnotation& annotation, const uint8_t maxZoom) {
auto it = symbolAnnotations.find(id);
if (it == symbolAnnotations.end()) {
removeAndAdd(id, annotation, maxZoom);
return Update::AnnotationData | Update::AnnotationStyle;
}

Update result = Update::Nothing;
const SymbolAnnotation& existing = it->second->annotation;

if (existing.geometry != annotation.geometry) {
result |= Update::AnnotationData;
}

if (existing.icon != annotation.icon) {
result |= Update::AnnotationData | Update::AnnotationStyle;
}

if (result != Update::Nothing) {
removeAndAdd(id, annotation, maxZoom);
}

return result;
}

Update AnnotationManager::update(const AnnotationID& id, const LineAnnotation& annotation, const uint8_t maxZoom) {
removeAndAdd(id, annotation, maxZoom);
return Update::AnnotationData | Update::AnnotationStyle;
}

Update AnnotationManager::update(const AnnotationID& id, const FillAnnotation& annotation, const uint8_t maxZoom) {
removeAndAdd(id, annotation, maxZoom);
return Update::AnnotationData | Update::AnnotationStyle;
}

Update AnnotationManager::update(const AnnotationID& id, const StyleSourcedAnnotation& annotation, const uint8_t maxZoom) {
removeAndAdd(id, annotation, maxZoom);
return Update::AnnotationData | Update::AnnotationStyle;
}

void AnnotationManager::removeAndAdd(const AnnotationID& id, const Annotation& annotation, const uint8_t maxZoom) {
removeAnnotation(id);
Annotation::visit(annotation, [&] (const auto& annotation_) {
this->add(id, annotation_, maxZoom);
});
}

AnnotationIDs AnnotationManager::getPointAnnotationsInBounds(const LatLngBounds& bounds) const {
AnnotationIDs result;

Expand Down Expand Up @@ -133,7 +179,9 @@ void AnnotationManager::updateStyle(Style& style) {
}

obsoleteShapeAnnotationLayers.clear();
}

void AnnotationManager::updateData() {
for (auto& tile : tiles) {
tile->setData(getTileData(tile->id.canonical));
}
Expand Down
13 changes: 11 additions & 2 deletions src/mbgl/annotation/annotation_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <mbgl/annotation/symbol_annotation_impl.hpp>
#include <mbgl/sprite/sprite_store.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/map/update.hpp>
#include <mbgl/util/noncopyable.hpp>

#include <string>
Expand All @@ -14,6 +14,7 @@

namespace mbgl {

class LatLngBounds;
class AnnotationTile;
class AnnotationTileData;
class SymbolAnnotationImpl;
Expand All @@ -29,7 +30,7 @@ class AnnotationManager : private util::noncopyable {
~AnnotationManager();

AnnotationID addAnnotation(const Annotation&, const uint8_t maxZoom);
void updateAnnotation(const AnnotationID&, const Annotation&, const uint8_t maxZoom);
Update updateAnnotation(const AnnotationID&, const Annotation&, const uint8_t maxZoom);
void removeAnnotation(const AnnotationID&);

AnnotationIDs getPointAnnotationsInBounds(const LatLngBounds&) const;
Expand All @@ -40,6 +41,7 @@ class AnnotationManager : private util::noncopyable {
SpriteAtlas& getSpriteAtlas() { return spriteAtlas; }

void updateStyle(style::Style&);
void updateData();

void addTile(AnnotationTile&);
void removeTile(AnnotationTile&);
Expand All @@ -53,6 +55,13 @@ class AnnotationManager : private util::noncopyable {
void add(const AnnotationID&, const FillAnnotation&, const uint8_t);
void add(const AnnotationID&, const StyleSourcedAnnotation&, const uint8_t);

Update update(const AnnotationID&, const SymbolAnnotation&, const uint8_t);
Update update(const AnnotationID&, const LineAnnotation&, const uint8_t);
Update update(const AnnotationID&, const FillAnnotation&, const uint8_t);
Update update(const AnnotationID&, const StyleSourcedAnnotation&, const uint8_t);

void removeAndAdd(const AnnotationID&, const Annotation&, const uint8_t);

std::unique_ptr<AnnotationTileData> getTileData(const CanonicalTileID&);

AnnotationID nextID = 0;
Expand Down
15 changes: 9 additions & 6 deletions src/mbgl/map/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,15 @@ void Map::Impl::update() {
// - Hint style sources to notify when all its tiles are loaded;
timePoint = Clock::now();

if (style->loaded && updateFlags & Update::Annotations) {
if (style->loaded && updateFlags & Update::AnnotationStyle) {
annotationManager->updateStyle(*style);
updateFlags |= Update::Classes;
}

if (updateFlags & Update::AnnotationData) {
annotationManager->updateData();
}

if (updateFlags & Update::Classes) {
style->cascade(timePoint, mode);
}
Expand Down Expand Up @@ -338,7 +342,7 @@ void Map::Impl::loadStyleJSON(const std::string& json) {
// force style cascade, causing all pending transitions to complete.
style->cascade(Clock::now(), mode);

updateFlags |= Update::Classes | Update::RecalculateStyle | Update::Annotations;
updateFlags |= Update::Classes | Update::RecalculateStyle | Update::AnnotationStyle;
asyncUpdate.send();
}

Expand Down Expand Up @@ -689,18 +693,17 @@ double Map::getTopOffsetPixelsForAnnotationIcon(const std::string& name) {

AnnotationID Map::addAnnotation(const Annotation& annotation) {
auto result = impl->annotationManager->addAnnotation(annotation, getMaxZoom());
update(Update::Annotations);
update(Update::AnnotationStyle | Update::AnnotationData);
return result;
}

void Map::updateAnnotation(AnnotationID id, const Annotation& annotation) {
impl->annotationManager->updateAnnotation(id, annotation, getMaxZoom());
update(Update::Annotations);
update(impl->annotationManager->updateAnnotation(id, annotation, getMaxZoom()));
}

void Map::removeAnnotation(AnnotationID annotation) {
impl->annotationManager->removeAnnotation(annotation);
update(Update::Annotations);
update(Update::AnnotationStyle | Update::AnnotationData);
}

AnnotationIDs Map::getPointAnnotationsInBounds(const LatLngBounds& bounds) {
Expand Down
4 changes: 2 additions & 2 deletions src/mbgl/tile/geojson_tile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ std::unique_ptr<GeoJSONTileData> convertTile(const mapbox::geojsonvt::Tile& tile
}

GeoJSONTile::GeoJSONTile(const OverscaledTileID& overscaledTileID,
std::string sourceID,
std::string sourceID_,
const style::UpdateParameters& parameters,
mapbox::geojsonvt::GeoJSONVT& geojsonvt)
: GeometryTile(overscaledTileID, sourceID, parameters.style, parameters.mode) {
: GeometryTile(overscaledTileID, sourceID_, parameters.style, parameters.mode) {
setData(convertTile(geojsonvt.getTile(id.canonical.z, id.canonical.x, id.canonical.y)));
}

Expand Down
4 changes: 2 additions & 2 deletions src/mbgl/tile/vector_tile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ class VectorTileData : public GeometryTileData {
};

VectorTile::VectorTile(const OverscaledTileID& id_,
std::string sourceID,
std::string sourceID_,
const style::UpdateParameters& parameters,
const Tileset& tileset)
: GeometryTile(id_, sourceID, parameters.style, parameters.mode),
: GeometryTile(id_, sourceID_, parameters.style, parameters.mode),
loader(*this, id_, parameters, tileset) {
}

Expand Down
20 changes: 9 additions & 11 deletions test/api/annotations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,23 +106,21 @@ TEST(Annotations, NonImmediateAdd) {
test.checkRendering("non_immediate_add");
}

TEST(Annotations, UpdateIcon) {
TEST(Annotations, UpdateSymbolAnnotationGeometry) {
AnnotationTest test;

test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
test.map.addAnnotationIcon("flipped_marker", namedMarker("default_marker.png"));
test.map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "flipped_marker" });
test.map.addAnnotationIcon("default_marker", namedMarker("default_marker.png"));
test.map.addAnnotationIcon("flipped_marker", namedMarker("flipped_marker.png"));
AnnotationID point = test.map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });

test::render(test.map);

test.map.removeAnnotationIcon("flipped_marker");
test.map.addAnnotationIcon("flipped_marker", namedMarker("flipped_marker.png"));
test.map.update(Update::Annotations);

test.checkRendering("update_icon");
test.map.updateAnnotation(point, SymbolAnnotation { Point<double> { -10, 0 }, "default_marker" });
test.checkRendering("update_point");
}

TEST(Annotations, UpdatePoint) {
TEST(Annotations, UpdateSymbolAnnotationIcon) {
AnnotationTest test;

test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
Expand All @@ -132,8 +130,8 @@ TEST(Annotations, UpdatePoint) {

test::render(test.map);

test.map.updateAnnotation(point, SymbolAnnotation { Point<double> { -10, 0 }, "flipped_marker" });
test.checkRendering("update_point");
test.map.updateAnnotation(point, SymbolAnnotation { Point<double> { 0, 0 }, "flipped_marker" });
test.checkRendering("update_icon");
}

TEST(Annotations, RemovePoint) {
Expand Down
Binary file modified test/fixtures/annotations/update_icon/expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/fixtures/annotations/update_point/expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2921127

Please sign in to comment.