diff options
author | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2019-05-03 16:11:41 +0300 |
---|---|---|
committer | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2019-05-21 06:49:17 -0700 |
commit | d24524440c949e02dddfbd9e4b23eb4e23ea9e69 (patch) | |
tree | e6b252007110aafcdf9b936e9d933647e0bdd8d8 /src | |
parent | 0344ce36c483dbbcf770ac7f2615a233b22c4452 (diff) | |
download | qtlocation-mapboxgl-d24524440c949e02dddfbd9e4b23eb4e23ea9e69.tar.gz |
[core] Add onRemoveUnusedStyleImages observer API
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/renderer/image_manager.cpp | 109 | ||||
-rw-r--r-- | src/mbgl/renderer/image_manager.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/renderer/image_manager_observer.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/renderer/renderer_impl.cpp | 11 |
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 76c45aef76..6647cecb94 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -511,9 +511,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) { @@ -521,6 +522,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) { @@ -661,10 +666,8 @@ void Renderer::Impl::reduceMemoryUse() { entry.second->reduceMemoryUse(); } backend.getContext().performCleanup(); + imageManager->reduceMemoryUse(); observer->onInvalidate(); - if (imageManager) { - imageManager->reduceMemoryUse(); - } } void Renderer::Impl::dumpDebugLogs() { |