diff options
Diffstat (limited to 'src/mbgl/renderer')
-rw-r--r-- | src/mbgl/renderer/image_atlas.cpp | 40 | ||||
-rw-r--r-- | src/mbgl/renderer/image_atlas.hpp | 16 | ||||
-rw-r--r-- | src/mbgl/renderer/image_manager.cpp | 53 | ||||
-rw-r--r-- | src/mbgl/renderer/image_manager.hpp | 12 | ||||
-rw-r--r-- | src/mbgl/renderer/image_manager_observer.hpp | 5 | ||||
-rw-r--r-- | src/mbgl/renderer/renderer_impl.cpp | 9 |
6 files changed, 107 insertions, 28 deletions
diff --git a/src/mbgl/renderer/image_atlas.cpp b/src/mbgl/renderer/image_atlas.cpp index b39c788ced..282f135ac9 100644 --- a/src/mbgl/renderer/image_atlas.cpp +++ b/src/mbgl/renderer/image_atlas.cpp @@ -1,4 +1,6 @@ #include <mbgl/renderer/image_atlas.hpp> +#include <mbgl/gfx/context.hpp> +#include <mbgl/renderer/image_manager.hpp> #include <mapbox/shelf-pack.hpp> @@ -6,14 +8,15 @@ namespace mbgl { static constexpr uint32_t padding = 1; -ImagePosition::ImagePosition(const mapbox::Bin& bin, const style::Image::Impl& image) +ImagePosition::ImagePosition(const mapbox::Bin& bin, const style::Image::Impl& image, uint32_t version_) : pixelRatio(image.pixelRatio), textureRect( bin.x + padding, bin.y + padding, bin.w - padding * 2, bin.h - padding * 2 - ) { + ), + version(version_) { } const mapbox::Bin& _packImage(mapbox::ShelfPack& pack, const style::Image::Impl& image, ImageAtlas& resultImage, ImageType imageType) { @@ -49,7 +52,30 @@ const mapbox::Bin& _packImage(mapbox::ShelfPack& pack, const style::Image::Impl& return bin; } -ImageAtlas makeImageAtlas(const ImageMap& icons, const ImageMap& patterns) { +void ImageAtlas::patchUpdatedImages(gfx::Context& context, gfx::Texture& atlasTexture, const ImageManager& imageManager) { + for (auto& updatedImageVersion : imageManager.updatedImageVersions) { + auto iconPosition = iconPositions.find(updatedImageVersion.first); + if (iconPosition != iconPositions.end()) { + patchUpdatedImage(context, atlasTexture, iconPosition->second, imageManager, updatedImageVersion.first, updatedImageVersion.second); + } + auto patternPosition = patternPositions.find(updatedImageVersion.first); + if (patternPosition != patternPositions.end()) { + patchUpdatedImage(context, atlasTexture, patternPosition->second, imageManager, updatedImageVersion.first, updatedImageVersion.second); + } + } +} + +void ImageAtlas::patchUpdatedImage(gfx::Context& context, gfx::Texture& atlasTexture, ImagePosition& position, const ImageManager& imageManager, const std::string& name, uint16_t version) { + if (position.version == version) return; + + auto updatedImage = imageManager.getImage(name); + if (updatedImage == nullptr) return; + + context.updateTextureSub(atlasTexture, updatedImage->image, position.textureRect.x, position.textureRect.y); + position.version = version; +} + +ImageAtlas makeImageAtlas(const ImageMap& icons, const ImageMap& patterns, const std::unordered_map<std::string, uint32_t>& versionMap) { ImageAtlas result; mapbox::ShelfPack::ShelfPackOptions options; @@ -59,13 +85,17 @@ ImageAtlas makeImageAtlas(const ImageMap& icons, const ImageMap& patterns) { for (const auto& entry : icons) { const style::Image::Impl& image = *entry.second; const mapbox::Bin& bin = _packImage(pack, image, result, ImageType::Icon); - result.iconPositions.emplace(image.id, ImagePosition { bin, image }); + auto it = versionMap.find(entry.first); + auto version = it != versionMap.end() ? it->second : 0; + result.iconPositions.emplace(image.id, ImagePosition { bin, image, version }); } for (const auto& entry : patterns) { const style::Image::Impl& image = *entry.second; const mapbox::Bin& bin = _packImage(pack, image, result, ImageType::Pattern); - result.patternPositions.emplace(image.id, ImagePosition { bin, image }); + auto it = versionMap.find(entry.first); + auto version = it != versionMap.end() ? it->second : 0; + result.patternPositions.emplace(image.id, ImagePosition { bin, image, version }); } pack.shrink(); diff --git a/src/mbgl/renderer/image_atlas.hpp b/src/mbgl/renderer/image_atlas.hpp index 3af31a75f8..080a490ab2 100644 --- a/src/mbgl/renderer/image_atlas.hpp +++ b/src/mbgl/renderer/image_atlas.hpp @@ -9,12 +9,20 @@ namespace mbgl { +namespace gfx { + class Texture; + class Context; +} // namespace gfx + +class ImageManager; + class ImagePosition { public: - ImagePosition(const mapbox::Bin&, const style::Image::Impl&); + ImagePosition(const mapbox::Bin&, const style::Image::Impl&, uint32_t version = 0); float pixelRatio; Rect<uint16_t> textureRect; + uint32_t version; std::array<uint16_t, 2> tl() const { return {{ @@ -51,8 +59,12 @@ public: PremultipliedImage image; ImagePositions iconPositions; ImagePositions patternPositions; + + void patchUpdatedImages(gfx::Context&, gfx::Texture&, const ImageManager&); +private: + void patchUpdatedImage(gfx::Context&, gfx::Texture&, ImagePosition& position, const ImageManager& imageManager, const std::string& name, uint16_t version); }; -ImageAtlas makeImageAtlas(const ImageMap&, const ImageMap&); +ImageAtlas makeImageAtlas(const ImageMap&, const ImageMap&, const std::unordered_map<std::string, uint32_t>& versionMap); } // namespace mbgl diff --git a/src/mbgl/renderer/image_manager.cpp b/src/mbgl/renderer/image_manager.cpp index 9f77bf9a97..fc54f2d8aa 100644 --- a/src/mbgl/renderer/image_manager.cpp +++ b/src/mbgl/renderer/image_manager.cpp @@ -35,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) { @@ -67,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) { @@ -79,10 +98,13 @@ void ImageManager::getImages(ImageRequestor& requestor, ImageRequestPair&& pair) } } } - if (isLoaded() || hasAllDependencies) { - checkMissingAndNotify(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)); } } @@ -103,7 +125,7 @@ void ImageManager::imagesAdded() { } void ImageManager::checkMissingAndNotify(ImageRequestor& requestor, const ImageRequestPair& pair) { - int missing = 0; + unsigned int missing = 0; for (const auto& dependency : pair.first) { auto it = images.find(dependency.first); if (it == images.end()) { @@ -114,15 +136,18 @@ void ImageManager::checkMissingAndNotify(ImageRequestor& requestor, const ImageR 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()) { - requestorIt ->second.callbacksRemaining--; + assert(requestorIt->second.callbacksRemaining > 0); + requestorIt->second.callbacksRemaining--; } }); } @@ -136,15 +161,21 @@ void ImageManager::checkMissingAndNotify(ImageRequestor& requestor, const ImageR void ImageManager::notify(ImageRequestor& requestor, const ImageRequestPair& pair) const { ImageMap iconMap; ImageMap patternMap; + std::unordered_map<std::string, uint32_t> 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 { diff --git a/src/mbgl/renderer/image_manager.hpp b/src/mbgl/renderer/image_manager.hpp index 789183dd1f..0ad634a029 100644 --- a/src/mbgl/renderer/image_manager.hpp +++ b/src/mbgl/renderer/image_manager.hpp @@ -22,7 +22,7 @@ class Context; class ImageRequestor { public: virtual ~ImageRequestor() = default; - virtual void onImagesAvailable(ImageMap icons, ImageMap patterns, uint64_t imageCorrelationID) = 0; + virtual void onImagesAvailable(ImageMap icons, ImageMap patterns, std::unordered_map<std::string, uint32_t> versionMap, uint64_t imageCorrelationID) = 0; }; /* @@ -50,25 +50,27 @@ public: const style::Image::Impl* getImage(const std::string&) const; void addImage(Immutable<style::Image::Impl>); - void updateImage(Immutable<style::Image::Impl>); + bool updateImage(Immutable<style::Image::Impl>); void removeImage(const std::string&); void getImages(ImageRequestor&, ImageRequestPair&&); void removeRequestor(ImageRequestor&); void imagesAdded(); + std::map<std::string, uint32_t> updatedImageVersions; + private: void checkMissingAndNotify(ImageRequestor&, const ImageRequestPair&); void notify(ImageRequestor&, const ImageRequestPair&) const; bool loaded = false; - std::unordered_map<ImageRequestor*, ImageRequestPair> requestors; + std::map<ImageRequestor*, ImageRequestPair> requestors; struct MissingImageRequestPair { ImageRequestPair pair; - int callbacksRemaining; + unsigned int callbacksRemaining; }; - std::unordered_map<ImageRequestor*, MissingImageRequestPair> missingImageRequestors; + std::map<ImageRequestor*, MissingImageRequestPair> missingImageRequestors; ImageMap images; ImageManagerObserver* observer = nullptr; diff --git a/src/mbgl/renderer/image_manager_observer.hpp b/src/mbgl/renderer/image_manager_observer.hpp index ff4ed1f48e..a8a6ca2d6c 100644 --- a/src/mbgl/renderer/image_manager_observer.hpp +++ b/src/mbgl/renderer/image_manager_observer.hpp @@ -1,12 +1,15 @@ #pragma once +#include <mbgl/renderer/renderer_observer.hpp> + namespace mbgl { class ImageManagerObserver { public: virtual ~ImageManagerObserver() = default; - virtual void onStyleImageMissing(const std::string&, std::function<void()>) {} + using StyleImageMissingCallback = std::function<void()>; + virtual void onStyleImageMissing(const std::string&, RendererObserver::StyleImageMissingCallback done) { done(); } }; } // namespace mbgl diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index e6ce6a63bd..3ad386717e 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -144,6 +144,9 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { const ImageDifference imageDiff = diffImages(imageImpls, updateParameters.images); imageImpls = updateParameters.images; + // Only trigger tile reparse for changed images. Changed images only need a relayout when they have a different size. + bool hasImageDiff = !imageDiff.removed.empty(); + // Remove removed images from sprite atlas. for (const auto& entry : imageDiff.removed) { imageManager->removeImage(entry.first); @@ -156,11 +159,11 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { // Update changed images. for (const auto& entry : imageDiff.changed) { - imageManager->updateImage(entry.second.after); + hasImageDiff = imageManager->updateImage(entry.second.after) || hasImageDiff; } - imageManager->setLoaded(updateParameters.spriteLoaded); imageManager->imagesAdded(); + imageManager->setLoaded(updateParameters.spriteLoaded); const LayerDifference layerDiff = diffLayers(layerImpls, updateParameters.layers); @@ -217,8 +220,6 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { renderSources.emplace(entry.first, std::move(renderSource)); } - const bool hasImageDiff = !(imageDiff.added.empty() && imageDiff.removed.empty() && imageDiff.changed.empty()); - // Update all sources. for (const auto& source : *sourceImpls) { std::vector<Immutable<Layer::Impl>> filteredLayers; |