summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Shalamov <alexander.shalamov@mapbox.com>2019-05-03 16:11:41 +0300
committerAlexander Shalamov <alexander.shalamov@mapbox.com>2019-05-16 04:54:46 +0300
commit79684f86d557eb2225de9c981d3bdf2a859e0b61 (patch)
treedc447a95a9566b5a3f8c85c160d1f1341c5a54e7
parent8dea1b0f067a1134d161afaa7864b7172c7c0578 (diff)
downloadqtlocation-mapboxgl-79684f86d557eb2225de9c981d3bdf2a859e0b61.tar.gz
[core] Add onRemoveUnusedStyleImages observer API
-rw-r--r--src/mbgl/renderer/image_manager.cpp109
-rw-r--r--src/mbgl/renderer/image_manager.hpp2
-rw-r--r--src/mbgl/renderer/image_manager_observer.hpp1
-rw-r--r--src/mbgl/renderer/renderer_impl.cpp11
4 files changed, 76 insertions, 47 deletions
diff --git a/src/mbgl/renderer/image_manager.cpp b/src/mbgl/renderer/image_manager.cpp
index 10375fe900..d5fe864fa7 100644
--- a/src/mbgl/renderer/image_manager.cpp
+++ b/src/mbgl/renderer/image_manager.cpp
@@ -1,4 +1,5 @@
#include <mbgl/renderer/image_manager.hpp>
+#include <mbgl/util/constants.hpp>
#include <mbgl/actor/actor.hpp>
#include <mbgl/actor/scheduler.hpp>
#include <mbgl/util/logging.hpp>
@@ -35,6 +36,10 @@ bool ImageManager::isLoaded() const {
void ImageManager::addImage(Immutable<style::Image::Impl> image_) {
assert(images.find(image_->id) == images.end());
+ // Increase cache size if requested image was provided.
+ if (requestedImages.find(image_->id) != requestedImages.end()) {
+ requestedImagesCacheSize += image_->image.bytes();
+ }
images.emplace(image_->id, std::move(image_));
}
@@ -46,6 +51,12 @@ bool ImageManager::updateImage(Immutable<style::Image::Impl> image_) {
auto sizeChanged = oldImage->second->image.size != image_->image.size;
if (sizeChanged) {
+ // Update cache size if requested image size has changed.
+ if (requestedImages.find(image_->id) != requestedImages.end()) {
+ int64_t diff = image_->image.bytes() - oldImage->second->image.bytes();
+ assert(static_cast<int64_t>(requestedImagesCacheSize + diff) >= 0ll);
+ requestedImagesCacheSize += diff;
+ }
updatedImageVersions.erase(image_->id);
} else {
updatedImageVersions[image_->id]++;
@@ -58,9 +69,16 @@ bool ImageManager::updateImage(Immutable<style::Image::Impl> image_) {
}
void ImageManager::removeImage(const std::string& id) {
- assert(images.find(id) != images.end());
- images.erase(id);
- requestedImages.erase(id);
+ auto it = images.find(id);
+ assert(it != images.end());
+ // Reduce cache size for requested images.
+ auto requestedIt = requestedImages.find(it->second->id);
+ if (requestedIt != requestedImages.end()) {
+ assert(requestedImagesCacheSize >= it->second->image.bytes());
+ requestedImagesCacheSize -= it->second->image.bytes();
+ requestedImages.erase(requestedIt);
+ }
+ images.erase(it);
removePattern(id);
}
@@ -102,12 +120,7 @@ void ImageManager::getImages(ImageRequestor& requestor, ImageRequestPair&& pair)
for (const auto& dependency : pair.first) {
if (images.find(dependency.first) == images.end()) {
hasAllDependencies = false;
- } else {
- // Associate requestor with an image that was provided by the client.
- auto it = requestedImages.find(dependency.first);
- if (it != requestedImages.end()) {
- it->second.emplace(&requestor);
- }
+ break;
}
}
@@ -141,57 +154,67 @@ void ImageManager::notifyIfMissingImageAdded() {
}
void ImageManager::reduceMemoryUse() {
- for (auto it = requestedImages.cbegin(); it != requestedImages.cend();) {
- if (it->second.empty() && images.find(it->first) != images.end()) {
- images.erase(it->first);
- removePattern(it->first);
- it = requestedImages.erase(it);
- } else {
- ++it;
+ std::vector<std::string> unusedIDs;
+ unusedIDs.reserve(requestedImages.size());
+
+ for (const auto& pair : requestedImages) {
+ if (pair.second.empty() && images.find(pair.first) != images.end()) {
+ unusedIDs.push_back(pair.first);
}
}
+
+ if (!unusedIDs.empty()) {
+ observer->onRemoveUnusedStyleImages(unusedIDs);
+ }
+}
+
+void ImageManager::reduceMemoryUseIfCacheSizeExceedsLimit() {
+ if (requestedImagesCacheSize > util::DEFAULT_ON_DEMAND_IMAGES_CACHE_SIZE) {
+ reduceMemoryUse();
+ }
}
void ImageManager::checkMissingAndNotify(ImageRequestor& requestor, const ImageRequestPair& pair) {
- unsigned int missing = 0;
+ std::vector<std::string> missingImages;
+ missingImages.reserve(pair.first.size());
for (const auto& dependency : pair.first) {
- auto it = images.find(dependency.first);
- if (it == images.end()) {
- missing++;
- requestedImages[dependency.first].emplace(&requestor);
+ if (images.find(dependency.first) == images.end()) {
+ missingImages.push_back(dependency.first);
}
}
- if (missing > 0) {
+ if (!missingImages.empty()) {
ImageRequestor* requestorPtr = &requestor;
auto emplaced = missingImageRequestors.emplace(requestorPtr, MissingImageRequestPair { pair, {} });
assert(emplaced.second);
+ for (const auto& missingImage : missingImages) {
+ assert(observer != nullptr);
+ requestedImages[missingImage].emplace(&requestor);
+ auto callback = std::make_unique<ActorCallback>(
+ *Scheduler::GetCurrent(),
+ [this, requestorPtr, missingImage] {
+ auto requestorIt = missingImageRequestors.find(requestorPtr);
+ if (requestorIt != missingImageRequestors.end()) {
+ assert(requestorIt->second.callbacks.find(missingImage) != requestorIt->second.callbacks.end());
+ requestorIt->second.callbacks.erase(missingImage);
+ }
+ });
+
+ auto actorRef = callback->self();
+ emplaced.first->second.callbacks.emplace(missingImage, std::move(callback));
+ observer->onStyleImageMissing(missingImage, [actorRef] {
+ actorRef.invoke(&Callback::operator());
+ });
+ }
+ } else {
+ // Associate requestor with an image that was provided by the client.
for (const auto& dependency : pair.first) {
- auto it = images.find(dependency.first);
- if (it == images.end()) {
- assert(observer != nullptr);
- auto callback = std::make_unique<ActorCallback>(
- *Scheduler::GetCurrent(),
- [this, requestorPtr, imageId = dependency.first] {
- auto requestorIt = missingImageRequestors.find(requestorPtr);
- if (requestorIt != missingImageRequestors.end()) {
- assert(requestorIt->second.callbacks.find(imageId) != requestorIt->second.callbacks.end());
- requestorIt->second.callbacks.erase(imageId);
- }
- });
-
- auto actorRef = callback->self();
- emplaced.first->second.callbacks.emplace(dependency.first, std::move(callback));
- observer->onStyleImageMissing(dependency.first, [actorRef]() {
- actorRef.invoke(&Callback::operator());
- });
-
+ if (requestedImages.find(dependency.first) != requestedImages.end()) {
+ requestedImages[dependency.first].emplace(&requestor);
}
}
-
- } else {
notify(requestor, pair);
}
}
diff --git a/src/mbgl/renderer/image_manager.hpp b/src/mbgl/renderer/image_manager.hpp
index 533259039f..f20d55415b 100644
--- a/src/mbgl/renderer/image_manager.hpp
+++ b/src/mbgl/renderer/image_manager.hpp
@@ -56,6 +56,7 @@ public:
void removeRequestor(ImageRequestor&);
void notifyIfMissingImageAdded();
void reduceMemoryUse();
+ void reduceMemoryUseIfCacheSizeExceedsLimit();
ImageVersionMap updatedImageVersions;
@@ -75,6 +76,7 @@ private:
};
std::map<ImageRequestor*, MissingImageRequestPair> missingImageRequestors;
std::map<std::string, std::set<ImageRequestor*>> requestedImages;
+ std::size_t requestedImagesCacheSize = 0ul;
ImageMap images;
ImageManagerObserver* observer = nullptr;
diff --git a/src/mbgl/renderer/image_manager_observer.hpp b/src/mbgl/renderer/image_manager_observer.hpp
index 3dc53c9b66..c2ca481d66 100644
--- a/src/mbgl/renderer/image_manager_observer.hpp
+++ b/src/mbgl/renderer/image_manager_observer.hpp
@@ -9,6 +9,7 @@ public:
virtual ~ImageManagerObserver() = default;
virtual void onStyleImageMissing(const std::string&, std::function<void()> done) { done(); }
+ virtual void onRemoveUnusedStyleImages(const std::vector<std::string>&) {}
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp
index 3f9b59a14a..15c38e1a6e 100644
--- a/src/mbgl/renderer/renderer_impl.cpp
+++ b/src/mbgl/renderer/renderer_impl.cpp
@@ -514,9 +514,10 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
}
#endif
+ const bool needsRepaint = isMapModeContinuous && hasTransitions(parameters.timePoint);
observer->onDidFinishRenderingFrame(
loaded ? RendererObserver::RenderMode::Full : RendererObserver::RenderMode::Partial,
- isMapModeContinuous && hasTransitions(parameters.timePoint)
+ needsRepaint
);
if (!loaded) {
@@ -524,6 +525,10 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
} else if (renderState != RenderState::Fully) {
renderState = RenderState::Fully;
observer->onDidFinishRenderingMap();
+ } else if (!needsRepaint) {
+ // Notify observer about unused images when map is fully loaded
+ // and there are no ongoing transitions.
+ imageManager->reduceMemoryUseIfCacheSizeExceedsLimit();
}
if (updateParameters.mode == MapMode::Continuous) {
@@ -664,10 +669,8 @@ void Renderer::Impl::reduceMemoryUse() {
entry.second->reduceMemoryUse();
}
backend.getContext().performCleanup();
+ imageManager->reduceMemoryUse();
observer->onInvalidate();
- if (imageManager) {
- imageManager->reduceMemoryUse();
- }
}
void Renderer::Impl::dumpDebugLogs() {