summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer/image_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/renderer/image_manager.cpp')
-rw-r--r--src/mbgl/renderer/image_manager.cpp100
1 files changed, 90 insertions, 10 deletions
diff --git a/src/mbgl/renderer/image_manager.cpp b/src/mbgl/renderer/image_manager.cpp
index 9c9f6c6e08..d2994d6f2d 100644
--- a/src/mbgl/renderer/image_manager.cpp
+++ b/src/mbgl/renderer/image_manager.cpp
@@ -1,9 +1,16 @@
#include <mbgl/renderer/image_manager.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/gfx/context.hpp>
+#include <mbgl/renderer/image_manager_observer.hpp>
namespace mbgl {
+static ImageManagerObserver nullObserver;
+
+void ImageManager::setObserver(ImageManagerObserver* observer_) {
+ observer = observer_ ? observer_ : &nullObserver;
+}
+
void ImageManager::setLoaded(bool loaded_) {
if (loaded == loaded_) {
return;
@@ -13,7 +20,7 @@ void ImageManager::setLoaded(bool loaded_) {
if (loaded) {
for (const auto& entry : requestors) {
- notify(*entry.first, entry.second);
+ checkMissingAndNotify(*entry.first, entry.second);
}
requestors.clear();
}
@@ -28,9 +35,23 @@ void ImageManager::addImage(Immutable<style::Image::Impl> image_) {
images.emplace(image_->id, std::move(image_));
}
-void ImageManager::updateImage(Immutable<style::Image::Impl> image_) {
+bool ImageManager::updateImage(Immutable<style::Image::Impl> image_) {
+ auto oldImage = images.find(image_->id);
+ assert(oldImage != images.end());
+ if (oldImage == images.end()) return false;
+
+ auto sizeChanged = oldImage->second->image.size != image_->image.size;
+
+ if (sizeChanged) {
+ updatedImageVersions.erase(image_->id);
+ } else {
+ updatedImageVersions[image_->id]++;
+ }
+
removeImage(image_->id);
addImage(std::move(image_));
+
+ return sizeChanged;
}
void ImageManager::removeImage(const std::string& id) {
@@ -60,10 +81,15 @@ const style::Image::Impl* ImageManager::getImage(const std::string& id) const {
}
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.
+ // remove previous requests from this tile
+ removeRequestor(requestor);
+
+ // If all the icon dependencies are already present ((i.e. if they've been addeded via
+ // runtime styling), then notify the requestor immediately. Otherwise, if the
+ // sprite has not loaded, then wait for it. When the sprite has loaded check
+ // if all icons are available. If any are missing, call `onStyleImageMissing`
+ // to give the user a chance to provide the icon. If they are not provided
+ // by the next frame we'll assume they are permanently missing.
bool hasAllDependencies = true;
if (!isLoaded()) {
for (const auto& dependency : pair.first) {
@@ -72,29 +98,83 @@ void ImageManager::getImages(ImageRequestor& requestor, ImageRequestPair&& pair)
}
}
}
- if (isLoaded() || hasAllDependencies) {
- notify(requestor, std::move(pair));
- } else {
+
+ if (hasAllDependencies) {
+ notify(requestor, pair);
+ } else if (!isLoaded()) {
requestors.emplace(&requestor, std::move(pair));
+ } else {
+ checkMissingAndNotify(requestor, std::move(pair));
}
}
void ImageManager::removeRequestor(ImageRequestor& requestor) {
requestors.erase(&requestor);
+ missingImageRequestors.erase(&requestor);
+}
+
+void ImageManager::notifyIfMissingImageAdded() {
+ for (auto it = missingImageRequestors.begin(); it != missingImageRequestors.end();) {
+ if (it->second.callbacksRemaining == 0) {
+ notify(*it->first, it->second.pair);
+ missingImageRequestors.erase(it++);
+ } else {
+ it++;
+ }
+ }
+}
+
+void ImageManager::checkMissingAndNotify(ImageRequestor& requestor, const ImageRequestPair& pair) {
+ unsigned int missing = 0;
+ for (const auto& dependency : pair.first) {
+ auto it = images.find(dependency.first);
+ if (it == images.end()) {
+ missing++;
+ }
+ }
+
+ if (missing > 0) {
+ ImageRequestor* requestorPtr = &requestor;
+
+ missingImageRequestors.emplace(requestorPtr, MissingImageRequestPair { std::move(pair), missing });
+
+ for (const auto& dependency : pair.first) {
+ auto it = images.find(dependency.first);
+ if (it == images.end()) {
+ assert(observer != nullptr);
+ observer->onStyleImageMissing(dependency.first, [this, requestorPtr]() {
+ auto requestorIt = missingImageRequestors.find(requestorPtr);
+ if (requestorIt != missingImageRequestors.end()) {
+ assert(requestorIt->second.callbacksRemaining > 0);
+ requestorIt->second.callbacksRemaining--;
+ }
+ });
+ }
+ }
+
+ } else {
+ notify(requestor, pair);
+ }
}
void ImageManager::notify(ImageRequestor& requestor, const ImageRequestPair& pair) const {
ImageMap iconMap;
ImageMap patternMap;
+ ImageVersionMap versionMap;
for (const auto& dependency : pair.first) {
auto it = images.find(dependency.first);
if (it != images.end()) {
dependency.second == ImageType::Pattern ? patternMap.emplace(*it) : iconMap.emplace(*it);
+
+ auto versionIt = updatedImageVersions.find(dependency.first);
+ if (versionIt != updatedImageVersions.end()) {
+ versionMap.emplace(versionIt->first, versionIt->second);
+ }
}
}
- requestor.onImagesAvailable(iconMap, patternMap, pair.second);
+ requestor.onImagesAvailable(iconMap, patternMap, std::move(versionMap), pair.second);
}
void ImageManager::dumpDebugLogs() const {