[core] Added GeometryTileWorker-owned image correlation ID

This commit is contained in:
Bruno de Oliveira Abinader
2017-08-25 11:47:34 +03:00
parent f3fc9b2b92
commit fe8cbc78d3
8 changed files with 48 additions and 24 deletions

View File

@@ -52,23 +52,23 @@ const style::Image::Impl* ImageManager::getImage(const std::string& id) const {
return nullptr;
}
void ImageManager::getImages(ImageRequestor& requestor, ImageDependencies dependencies) {
void ImageManager::getImages(ImageRequestor& requestor, ImageRequestPair&& pair) {
// If the sprite has been loaded, or if all the icon dependencies are already present
// (i.e. if they've been addeded via runtime styling), then notify the requestor immediately.
// Otherwise, delay notification until the sprite is loaded. At that point, if any of the
// dependencies are still unavailable, we'll just assume they are permanently missing.
bool hasAllDependencies = true;
if (!isLoaded()) {
for (const auto& dependency : dependencies) {
for (const auto& dependency : pair.first) {
if (images.find(dependency) == images.end()) {
hasAllDependencies = false;
}
}
}
if (isLoaded() || hasAllDependencies) {
notify(requestor, dependencies);
notify(requestor, std::move(pair));
} else {
requestors.emplace(&requestor, std::move(dependencies));
requestors.emplace(&requestor, std::move(pair));
}
}
@@ -76,17 +76,17 @@ void ImageManager::removeRequestor(ImageRequestor& requestor) {
requestors.erase(&requestor);
}
void ImageManager::notify(ImageRequestor& requestor, const ImageDependencies& dependencies) const {
void ImageManager::notify(ImageRequestor& requestor, const ImageRequestPair& pair) const {
ImageMap response;
for (const auto& dependency : dependencies) {
for (const auto& dependency : pair.first) {
auto it = images.find(dependency);
if (it != images.end()) {
response.emplace(*it);
}
}
requestor.onImagesAvailable(response);
requestor.onImagesAvailable(response, pair.second);
}
void ImageManager::dumpDebugLogs() const {

View File

@@ -21,7 +21,7 @@ class Context;
class ImageRequestor {
public:
virtual ~ImageRequestor() = default;
virtual void onImagesAvailable(ImageMap) = 0;
virtual void onImagesAvailable(ImageMap, uint64_t imageCorrelationID) = 0;
};
/*
@@ -50,15 +50,15 @@ public:
void updateImage(Immutable<style::Image::Impl>);
void removeImage(const std::string&);
void getImages(ImageRequestor&, ImageDependencies);
void getImages(ImageRequestor&, ImageRequestPair&&);
void removeRequestor(ImageRequestor&);
private:
void notify(ImageRequestor&, const ImageDependencies&) const;
void notify(ImageRequestor&, const ImageRequestPair&) const;
bool loaded = false;
std::unordered_map<ImageRequestor*, ImageDependencies> requestors;
std::unordered_map<ImageRequestor*, ImageRequestPair> requestors;
ImageMap images;
// Pattern stuff

View File

@@ -28,5 +28,6 @@ public:
using ImageMap = std::unordered_map<std::string, Immutable<style::Image::Impl>>;
using ImageDependencies = std::set<std::string>;
using ImageRequestPair = std::pair<ImageDependencies, uint64_t>;
} // namespace mbgl

View File

@@ -28,6 +28,22 @@ namespace mbgl {
using namespace style;
/*
Correlation between GeometryTile and GeometryTileWorker is safeguarded by two
correlation schemes:
GeometryTile's 'correlationID' is used for ensuring the tile will be flagged
as non-pending only when the placement coming from the last operation (as in
'setData', 'setLayers', 'setPlacementConfig') occurs. This is important for
still mode rendering as we want to render only when all layout and placement
operations are completed.
GeometryTileWorker's 'imageCorrelationID' is used for checking whether an
image request reply coming from `GeometryTile` is valid. Previous image
request replies are ignored as they result in incomplete placement attempts
that could flag the tile as non-pending too early.
*/
GeometryTile::GeometryTile(const OverscaledTileID& id_,
std::string sourceID_,
const TileParameters& parameters)
@@ -170,12 +186,12 @@ void GeometryTile::getGlyphs(GlyphDependencies glyphDependencies) {
glyphManager.getGlyphs(*this, std::move(glyphDependencies));
}
void GeometryTile::onImagesAvailable(ImageMap images) {
worker.invoke(&GeometryTileWorker::onImagesAvailable, std::move(images));
void GeometryTile::onImagesAvailable(ImageMap images, uint64_t imageCorrelationID) {
worker.invoke(&GeometryTileWorker::onImagesAvailable, std::move(images), imageCorrelationID);
}
void GeometryTile::getImages(ImageDependencies imageDependencies) {
imageManager.getImages(*this, std::move(imageDependencies));
void GeometryTile::getImages(ImageRequestPair pair) {
imageManager.getImages(*this, std::move(pair));
}
void GeometryTile::upload(gl::Context& context) {

View File

@@ -40,10 +40,10 @@ public:
void setLayers(const std::vector<Immutable<style::Layer::Impl>>&) override;
void onGlyphsAvailable(GlyphMap) override;
void onImagesAvailable(ImageMap) override;
void onImagesAvailable(ImageMap, uint64_t imageCorrelationID) override;
void getGlyphs(GlyphDependencies);
void getImages(ImageDependencies);
void getImages(ImageRequestPair);
void upload(gl::Context&) override;
Bucket* getBucket(const style::Layer::Impl&) const override;

View File

@@ -216,7 +216,10 @@ void GeometryTileWorker::onGlyphsAvailable(GlyphMap newGlyphMap) {
symbolDependenciesChanged();
}
void GeometryTileWorker::onImagesAvailable(ImageMap newImageMap) {
void GeometryTileWorker::onImagesAvailable(ImageMap newImageMap, uint64_t imageCorrelationID_) {
if (imageCorrelationID != imageCorrelationID_) {
return; // Ignore outdated image request replies.
}
imageMap = std::move(newImageMap);
pendingImageDependencies.clear();
symbolDependenciesChanged();
@@ -239,7 +242,7 @@ void GeometryTileWorker::requestNewGlyphs(const GlyphDependencies& glyphDependen
void GeometryTileWorker::requestNewImages(const ImageDependencies& imageDependencies) {
pendingImageDependencies = imageDependencies;
if (!pendingImageDependencies.empty()) {
parent.invoke(&GeometryTile::getImages, pendingImageDependencies);
parent.invoke(&GeometryTile::getImages, std::make_pair(pendingImageDependencies, ++imageCorrelationID));
}
}

View File

@@ -38,7 +38,7 @@ public:
void setPlacementConfig(PlacementConfig, uint64_t correlationID);
void onGlyphsAvailable(GlyphMap glyphs);
void onImagesAvailable(ImageMap images);
void onImagesAvailable(ImageMap images, uint64_t imageCorrelationID);
private:
void coalesced();
@@ -70,6 +70,7 @@ private:
State state = Idle;
uint64_t correlationID = 0;
uint64_t imageCorrelationID = 0;
// Outer optional indicates whether we've received it or not.
optional<std::vector<Immutable<style::Layer::Impl>>> layers;

View File

@@ -108,11 +108,12 @@ TEST(ImageManager, RemoveReleasesBinPackRect) {
class StubImageRequestor : public ImageRequestor {
public:
void onImagesAvailable(ImageMap images) final {
if (imagesAvailable) imagesAvailable(images);
void onImagesAvailable(ImageMap images, uint64_t imageCorrelationID_) final {
if (imagesAvailable && imageCorrelationID == imageCorrelationID_) imagesAvailable(images);
}
std::function<void (ImageMap)> imagesAvailable;
uint64_t imageCorrelationID = 0;
};
TEST(ImageManager, NotifiesRequestorWhenSpriteIsLoaded) {
@@ -124,7 +125,8 @@ TEST(ImageManager, NotifiesRequestorWhenSpriteIsLoaded) {
notified = true;
};
imageManager.getImages(requestor, {"one"});
uint64_t imageCorrelationID = 0;
imageManager.getImages(requestor, std::make_pair(std::set<std::string> {"one"}, imageCorrelationID));
ASSERT_FALSE(notified);
imageManager.setLoaded(true);
@@ -140,8 +142,9 @@ TEST(ImageManager, NotifiesRequestorImmediatelyIfDependenciesAreSatisfied) {
notified = true;
};
uint64_t imageCorrelationID = 0;
imageManager.addImage(makeMutable<style::Image::Impl>("one", PremultipliedImage({ 16, 16 }), 2));
imageManager.getImages(requestor, {"one"});
imageManager.getImages(requestor, std::make_pair(std::set<std::string> {"one"}, imageCorrelationID));
ASSERT_TRUE(notified);
}