summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2020-02-11 01:54:05 +0200
committerMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2020-02-11 14:34:46 +0200
commit64e2bcdf4395a1c65cd9faca81f98c4c5d974bd6 (patch)
tree672f0cb62600314c76c26478d44ebf6d56c96577 /src
parent146e0ac8ed6a287b77505ffdefa9fe77da93eee1 (diff)
downloadqtlocation-mapboxgl-64e2bcdf4395a1c65cd9faca81f98c4c5d974bd6.tar.gz
[core] Loading images to style optimization
This change enables attaching images to the style with batches and avoids massive re-allocations. Thus, it improves UI performance especially at start-up time.
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/map/map_impl.cpp1
-rw-r--r--src/mbgl/sprite/sprite_loader.cpp2
-rw-r--r--src/mbgl/sprite/sprite_loader.hpp5
-rw-r--r--src/mbgl/sprite/sprite_loader_observer.hpp7
-rw-r--r--src/mbgl/sprite/sprite_parser.cpp72
-rw-r--r--src/mbgl/sprite/sprite_parser.hpp2
-rw-r--r--src/mbgl/style/style.cpp16
-rw-r--r--src/mbgl/style/style_impl.cpp44
-rw-r--r--src/mbgl/style/style_impl.hpp9
9 files changed, 94 insertions, 64 deletions
diff --git a/src/mbgl/map/map_impl.cpp b/src/mbgl/map/map_impl.cpp
index bc2a37fe07..e4eb2e3e8c 100644
--- a/src/mbgl/map/map_impl.cpp
+++ b/src/mbgl/map/map_impl.cpp
@@ -170,7 +170,6 @@ void Map::Impl::jumpTo(const CameraOptions& camera) {
}
void Map::Impl::onStyleImageMissing(const std::string& id, std::function<void()> done) {
-
if (style->getImage(id) == nullptr) {
observer.onStyleImageMissing(id);
}
diff --git a/src/mbgl/sprite/sprite_loader.cpp b/src/mbgl/sprite/sprite_loader.cpp
index d4b1cade13..56f7abd50b 100644
--- a/src/mbgl/sprite/sprite_loader.cpp
+++ b/src/mbgl/sprite/sprite_loader.cpp
@@ -90,7 +90,7 @@ void SpriteLoader::emitSpriteLoadedIfComplete() {
loader->worker.self().invoke(&SpriteLoaderWorker::parse, loader->image, loader->json);
}
-void SpriteLoader::onParsed(std::vector<std::unique_ptr<style::Image>>&& result) {
+void SpriteLoader::onParsed(std::vector<Immutable<style::Image::Impl>> result) {
observer->onSpriteLoaded(std::move(result));
}
diff --git a/src/mbgl/sprite/sprite_loader.hpp b/src/mbgl/sprite/sprite_loader.hpp
index 0b7d37fa14..d82c51e2da 100644
--- a/src/mbgl/sprite/sprite_loader.hpp
+++ b/src/mbgl/sprite/sprite_loader.hpp
@@ -1,6 +1,5 @@
#pragma once
-#include <mbgl/util/noncopyable.hpp>
#include <mbgl/style/image.hpp>
#include <string>
@@ -15,7 +14,7 @@ namespace mbgl {
class FileSource;
class SpriteLoaderObserver;
-class SpriteLoader : public util::noncopyable {
+class SpriteLoader {
public:
SpriteLoader(float pixelRatio);
~SpriteLoader();
@@ -29,7 +28,7 @@ private:
// Invoked by SpriteAtlasWorker
friend class SpriteLoaderWorker;
- void onParsed(std::vector<std::unique_ptr<style::Image>>&&);
+ void onParsed(std::vector<Immutable<style::Image::Impl>>);
void onError(std::exception_ptr);
const float pixelRatio;
diff --git a/src/mbgl/sprite/sprite_loader_observer.hpp b/src/mbgl/sprite/sprite_loader_observer.hpp
index c730549c2c..3846d069f0 100644
--- a/src/mbgl/sprite/sprite_loader_observer.hpp
+++ b/src/mbgl/sprite/sprite_loader_observer.hpp
@@ -1,7 +1,9 @@
#pragma once
+#include <mbgl/style/image.hpp>
+#include <mbgl/util/immutable.hpp>
+
#include <exception>
-#include <memory>
#include <vector>
namespace mbgl {
@@ -13,8 +15,7 @@ class Image;
class SpriteLoaderObserver {
public:
virtual ~SpriteLoaderObserver() = default;
-
- virtual void onSpriteLoaded(std::vector<std::unique_ptr<style::Image>>&&) {}
+ virtual void onSpriteLoaded(std::vector<Immutable<style::Image::Impl>>) {}
virtual void onSpriteError(std::exception_ptr) {}
};
diff --git a/src/mbgl/sprite/sprite_parser.cpp b/src/mbgl/sprite/sprite_parser.cpp
index d39428a848..40e63d2d7d 100644
--- a/src/mbgl/sprite/sprite_parser.cpp
+++ b/src/mbgl/sprite/sprite_parser.cpp
@@ -149,50 +149,54 @@ optional<style::ImageContent> getContent(const JSValue& value, const char* prope
} // namespace
-std::vector<std::unique_ptr<style::Image>> parseSprite(const std::string& encodedImage, const std::string& json) {
+std::vector<Immutable<style::Image::Impl>> parseSprite(const std::string& encodedImage, const std::string& json) {
const PremultipliedImage raster = decodeImage(encodedImage);
JSDocument doc;
doc.Parse<0>(json.c_str());
if (doc.HasParseError()) {
throw std::runtime_error("Failed to parse JSON: " + formatJSONParseError(doc));
- } else if (!doc.IsObject()) {
+ }
+
+ if (!doc.IsObject()) {
throw std::runtime_error("Sprite JSON root must be an object");
- } else {
- std::vector<std::unique_ptr<style::Image>> images;
- for (const auto& property : doc.GetObject()) {
- const std::string name = { property.name.GetString(), property.name.GetStringLength() };
- const JSValue& value = property.value;
-
- if (value.IsObject()) {
- const uint16_t x = getUInt16(value, "x", name.c_str(), 0);
- const uint16_t y = getUInt16(value, "y", name.c_str(), 0);
- const uint16_t width = getUInt16(value, "width", name.c_str(), 0);
- const uint16_t height = getUInt16(value, "height", name.c_str(), 0);
- const double pixelRatio = getDouble(value, "pixelRatio", name.c_str(), 1);
- const bool sdf = getBoolean(value, "sdf", name.c_str(), false);
- style::ImageStretches stretchX = getStretches(value, "stretchX", name.c_str());
- style::ImageStretches stretchY = getStretches(value, "stretchY", name.c_str());
- optional<style::ImageContent> content = getContent(value, "content", name.c_str());
-
- auto image = createStyleImage(name,
- raster,
- x,
- y,
- width,
- height,
- pixelRatio,
- sdf,
- std::move(stretchX),
- std::move(stretchY),
- std::move(content));
- if (image) {
- images.push_back(std::move(image));
- }
+ }
+
+ const auto& properties = doc.GetObject();
+ std::vector<Immutable<style::Image::Impl>> images;
+ images.reserve(properties.MemberCount());
+ for (const auto& property : properties) {
+ const std::string name = {property.name.GetString(), property.name.GetStringLength()};
+ const JSValue& value = property.value;
+
+ if (value.IsObject()) {
+ const uint16_t x = getUInt16(value, "x", name.c_str(), 0);
+ const uint16_t y = getUInt16(value, "y", name.c_str(), 0);
+ const uint16_t width = getUInt16(value, "width", name.c_str(), 0);
+ const uint16_t height = getUInt16(value, "height", name.c_str(), 0);
+ const double pixelRatio = getDouble(value, "pixelRatio", name.c_str(), 1);
+ const bool sdf = getBoolean(value, "sdf", name.c_str(), false);
+ style::ImageStretches stretchX = getStretches(value, "stretchX", name.c_str());
+ style::ImageStretches stretchY = getStretches(value, "stretchY", name.c_str());
+ optional<style::ImageContent> content = getContent(value, "content", name.c_str());
+
+ auto image = createStyleImage(name,
+ raster,
+ x,
+ y,
+ width,
+ height,
+ pixelRatio,
+ sdf,
+ std::move(stretchX),
+ std::move(stretchY),
+ std::move(content));
+ if (image) {
+ images.push_back(std::move(image->baseImpl));
}
}
- return images;
}
+ return images;
}
} // namespace mbgl
diff --git a/src/mbgl/sprite/sprite_parser.hpp b/src/mbgl/sprite/sprite_parser.hpp
index 9656bcbf2a..f2e7358ac2 100644
--- a/src/mbgl/sprite/sprite_parser.hpp
+++ b/src/mbgl/sprite/sprite_parser.hpp
@@ -20,6 +20,6 @@ std::unique_ptr<style::Image> createStyleImage(const std::string& id,
optional<style::ImageContent> content = nullopt);
// Parses an image and an associated JSON file and returns the sprite objects.
-std::vector<std::unique_ptr<style::Image>> parseSprite(const std::string& image, const std::string& json);
+std::vector<Immutable<style::Image::Impl>> parseSprite(const std::string& image, const std::string& json);
} // namespace mbgl
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index 8a821e5a5e..1814ba8adb 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -1,9 +1,10 @@
-#include <mbgl/style/style.hpp>
-#include <mbgl/style/style_impl.hpp>
-#include <mbgl/style/light.hpp>
#include <mbgl/style/image.hpp>
-#include <mbgl/style/source.hpp>
+#include <mbgl/style/image_impl.hpp>
#include <mbgl/style/layer.hpp>
+#include <mbgl/style/light.hpp>
+#include <mbgl/style/source.hpp>
+#include <mbgl/style/style.hpp>
+#include <mbgl/style/style_impl.hpp>
namespace mbgl {
namespace style {
@@ -59,8 +60,11 @@ const Light* Style::getLight() const {
return impl->getLight();
}
-const Image* Style::getImage(const std::string& name) const {
- return impl->getImage(name);
+const PremultipliedImage* Style::getImage(const std::string& name) const {
+ if (auto* image = impl->getImage(name)) {
+ return &(image->image);
+ }
+ return nullptr;
}
void Style::addImage(std::unique_ptr<Image> image) {
diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp
index 5b52f1d72c..2d4376073d 100644
--- a/src/mbgl/style/style_impl.cpp
+++ b/src/mbgl/style/style_impl.cpp
@@ -98,7 +98,7 @@ void Style::Impl::parse(const std::string& json_) {
sources.clear();
layers.clear();
- images.clear();
+ images = makeMutable<ImageImpls>();
transitionOptions = parser.transition;
@@ -274,17 +274,37 @@ bool Style::Impl::isLoaded() const {
}
void Style::Impl::addImage(std::unique_ptr<style::Image> image) {
- images.remove(image->getID()); // We permit using addImage to update.
- images.add(std::move(image));
+ auto newImages = makeMutable<ImageImpls>(*images);
+ auto it =
+ std::lower_bound(newImages->begin(), newImages->end(), image->getID(), [](const auto& a, const std::string& b) {
+ return a->id < b;
+ });
+ if (it != newImages->end() && (*it)->id == image->getID()) {
+ // We permit using addImage to update.
+ *it = std::move(image->baseImpl);
+ } else {
+ newImages->insert(it, std::move(image->baseImpl));
+ }
+ images = std::move(newImages);
observer->onUpdate();
}
void Style::Impl::removeImage(const std::string& id) {
- images.remove(id);
+ auto newImages = makeMutable<ImageImpls>(*images);
+ auto found =
+ std::find_if(newImages->begin(), newImages->end(), [&id](const auto& image) { return image->id == id; });
+ if (found == images->end()) {
+ Log::Warning(Event::General, "Image '%s' is not present in style, cannot remove", id.c_str());
+ return;
+ }
+ newImages->erase(found);
+ images = std::move(newImages);
}
-const style::Image* Style::Impl::getImage(const std::string& id) const {
- return images.get(id);
+const style::Image::Impl* Style::Impl::getImage(const std::string& id) const {
+ auto found = std::find_if(images->begin(), images->end(), [&id](const auto& image) { return image->id == id; });
+ if (found == images->end()) return nullptr;
+ return found->get();
}
void Style::Impl::setObserver(style::Observer* observer_) {
@@ -319,10 +339,12 @@ void Style::Impl::onSourceDescriptionChanged(Source& source) {
}
}
-void Style::Impl::onSpriteLoaded(std::vector<std::unique_ptr<Image>>&& images_) {
- for (auto& image : images_) {
- addImage(std::move(image));
- }
+void Style::Impl::onSpriteLoaded(std::vector<Immutable<style::Image::Impl>> images_) {
+ auto newImages = makeMutable<ImageImpls>(*images);
+ newImages->insert(
+ newImages->end(), std::make_move_iterator(images_.begin()), std::make_move_iterator(images_.end()));
+ std::sort(newImages->begin(), newImages->end(), [](const auto& a, const auto& b) { return a->id < b->id; });
+ images = std::move(newImages);
spriteLoaded = true;
observer->onUpdate(); // For *-pattern properties.
}
@@ -357,7 +379,7 @@ const std::string& Style::Impl::getGlyphURL() const {
}
Immutable<std::vector<Immutable<Image::Impl>>> Style::Impl::getImageImpls() const {
- return images.getImpls();
+ return images;
}
Immutable<std::vector<Immutable<Source::Impl>>> Style::Impl::getSourceImpls() const {
diff --git a/src/mbgl/style/style_impl.hpp b/src/mbgl/style/style_impl.hpp
index ca165e24f0..f7dc7af293 100644
--- a/src/mbgl/style/style_impl.hpp
+++ b/src/mbgl/style/style_impl.hpp
@@ -78,13 +78,14 @@ public:
void setLight(std::unique_ptr<Light>);
Light* getLight() const;
- const style::Image* getImage(const std::string&) const;
+ const style::Image::Impl* getImage(const std::string&) const;
void addImage(std::unique_ptr<style::Image>);
void removeImage(const std::string&);
const std::string& getGlyphURL() const;
- Immutable<std::vector<Immutable<Image::Impl>>> getImageImpls() const;
+ using ImageImpls = std::vector<Immutable<Image::Impl>>;
+ Immutable<ImageImpls> getImageImpls() const;
Immutable<std::vector<Immutable<Source::Impl>>> getSourceImpls() const;
Immutable<std::vector<Immutable<Layer::Impl>>> getLayerImpls() const;
@@ -106,7 +107,7 @@ private:
std::unique_ptr<SpriteLoader> spriteLoader;
std::string glyphURL;
- CollectionWithPersistentOrder<style::Image> images;
+ Immutable<ImageImpls> images = makeMutable<ImageImpls>();
CollectionWithPersistentOrder<Source> sources;
Collection<Layer> layers;
TransitionOptions transitionOptions;
@@ -117,7 +118,7 @@ private:
CameraOptions defaultCamera;
// SpriteLoaderObserver implementation.
- void onSpriteLoaded(std::vector<std::unique_ptr<Image>>&&) override;
+ void onSpriteLoaded(std::vector<Immutable<style::Image::Impl>>) override;
void onSpriteError(std::exception_ptr) override;
// SourceObserver implementation.