summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/renderer')
-rw-r--r--src/mbgl/renderer/image_atlas.cpp40
-rw-r--r--src/mbgl/renderer/image_atlas.hpp16
-rw-r--r--src/mbgl/renderer/image_manager.cpp53
-rw-r--r--src/mbgl/renderer/image_manager.hpp12
-rw-r--r--src/mbgl/renderer/image_manager_observer.hpp5
-rw-r--r--src/mbgl/renderer/renderer_impl.cpp9
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;