diff options
author | Brad Leege <bleege@gmail.com> | 2015-03-23 10:52:27 -0500 |
---|---|---|
committer | Brad Leege <bleege@gmail.com> | 2015-03-23 10:52:27 -0500 |
commit | 044d1fc3c258ca435880d1adbcdbc34fc67c2d24 (patch) | |
tree | b9ff72fa70779857959d864b8ac8e390e4431c9f /src/mbgl | |
parent | 33f4dfffd2d9ef20d803e495c47b1248b51bd12c (diff) | |
parent | 9d30d4042c3311d02568adbb38dd13fb82faf75d (diff) | |
download | qtlocation-mapboxgl-044d1fc3c258ca435880d1adbcdbc34fc67c2d24.tar.gz |
Merge branch 'master' of github.com:mapbox/mapbox-gl-native into 1033-metrics
Conflicts:
gyp/platform-ios.gypi
platform/ios/MGLMapView.mm
styles
Diffstat (limited to 'src/mbgl')
-rw-r--r-- | src/mbgl/geometry/buffer.hpp | 3 | ||||
-rw-r--r-- | src/mbgl/geometry/line_atlas.cpp | 6 | ||||
-rw-r--r-- | src/mbgl/geometry/sprite_atlas.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/geometry/vao.cpp | 3 | ||||
-rw-r--r-- | src/mbgl/map/annotation.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/map/environment.cpp | 55 | ||||
-rw-r--r-- | src/mbgl/map/environment.hpp | 42 | ||||
-rw-r--r-- | src/mbgl/map/map.cpp | 237 | ||||
-rw-r--r-- | src/mbgl/map/map_data.cpp | 44 | ||||
-rw-r--r-- | src/mbgl/map/map_data.hpp | 102 | ||||
-rw-r--r-- | src/mbgl/map/tile_data.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/util/texture_pool.cpp | 15 |
12 files changed, 395 insertions, 122 deletions
diff --git a/src/mbgl/geometry/buffer.hpp b/src/mbgl/geometry/buffer.hpp index 3649574bbf..4198425ecf 100644 --- a/src/mbgl/geometry/buffer.hpp +++ b/src/mbgl/geometry/buffer.hpp @@ -3,6 +3,7 @@ #include <mbgl/platform/gl.hpp> #include <mbgl/util/noncopyable.hpp> +#include <mbgl/map/environment.hpp> #include <cstdlib> #include <cassert> @@ -21,7 +22,7 @@ public: ~Buffer() { cleanup(); if (buffer != 0) { - MBGL_CHECK_ERROR(glDeleteBuffers(1, &buffer)); + Environment::Get().abandonBuffer(buffer); buffer = 0; } } diff --git a/src/mbgl/geometry/line_atlas.cpp b/src/mbgl/geometry/line_atlas.cpp index 8be1a8d53c..507cc7b087 100644 --- a/src/mbgl/geometry/line_atlas.cpp +++ b/src/mbgl/geometry/line_atlas.cpp @@ -1,3 +1,4 @@ +#include <mbgl/map/environment.hpp> #include <mbgl/geometry/line_atlas.hpp> #include <mbgl/platform/gl.hpp> #include <mbgl/platform/log.hpp> @@ -18,9 +19,10 @@ LineAtlas::LineAtlas(uint16_t w, uint16_t h) LineAtlas::~LineAtlas() { std::lock_guard<std::recursive_mutex> lock(mtx); - MBGL_CHECK_ERROR(glDeleteTextures(1, &texture)); - delete[] data; + Environment::Get().abandonTexture(texture); texture = 0; + + delete[] data; } LinePatternPos LineAtlas::getDashPosition(const std::vector<float> &dasharray, bool round) { diff --git a/src/mbgl/geometry/sprite_atlas.cpp b/src/mbgl/geometry/sprite_atlas.cpp index dce772f2e4..bf31c6e38e 100644 --- a/src/mbgl/geometry/sprite_atlas.cpp +++ b/src/mbgl/geometry/sprite_atlas.cpp @@ -1,3 +1,4 @@ +#include <mbgl/map/environment.hpp> #include <mbgl/geometry/sprite_atlas.hpp> #include <mbgl/platform/gl.hpp> #include <mbgl/platform/log.hpp> @@ -293,8 +294,7 @@ void SpriteAtlas::bind(bool linear) { SpriteAtlas::~SpriteAtlas() { std::lock_guard<std::recursive_mutex> lock(mtx); - - MBGL_CHECK_ERROR(glDeleteTextures(1, &texture)); + Environment::Get().abandonTexture(texture); texture = 0; ::operator delete(data), data = nullptr; } diff --git a/src/mbgl/geometry/vao.cpp b/src/mbgl/geometry/vao.cpp index 00976b4d54..fef74396a9 100644 --- a/src/mbgl/geometry/vao.cpp +++ b/src/mbgl/geometry/vao.cpp @@ -1,6 +1,7 @@ #include <mbgl/geometry/vao.hpp> #include <mbgl/platform/log.hpp> #include <mbgl/util/string.hpp> +#include <mbgl/map/environment.hpp> namespace mbgl { @@ -11,7 +12,7 @@ VertexArrayObject::~VertexArrayObject() { if (!gl::DeleteVertexArrays) return; if (vao) { - MBGL_CHECK_ERROR(gl::DeleteVertexArrays(1, &vao)); + Environment::Get().abandonVAO(vao); } } diff --git a/src/mbgl/map/annotation.cpp b/src/mbgl/map/annotation.cpp index 0d6da5781e..83739ab46a 100644 --- a/src/mbgl/map/annotation.cpp +++ b/src/mbgl/map/annotation.cpp @@ -40,7 +40,9 @@ std::pair<std::vector<Tile::ID>, std::vector<uint32_t>> AnnotationManager::addPo uint16_t extent = 4096; - std::vector<uint32_t> annotationIDs(points.size()); + std::vector<uint32_t> annotationIDs; + annotationIDs.reserve(points.size()); + std::vector<Tile::ID> affectedTiles; for (uint32_t i = 0; i < points.size(); ++i) { diff --git a/src/mbgl/map/environment.cpp b/src/mbgl/map/environment.cpp index 1aea5aa0c9..469790501c 100644 --- a/src/mbgl/map/environment.cpp +++ b/src/mbgl/map/environment.cpp @@ -1,5 +1,6 @@ #include <mbgl/map/environment.hpp> #include <mbgl/storage/file_source.hpp> +#include <mbgl/platform/gl.hpp> #include <uv.h> @@ -76,12 +77,12 @@ ThreadInfoStore threadInfoStore; } // namespace -Environment::Scope::Scope(Environment& env, ThreadType type, const std::string& name) +EnvironmentScope::EnvironmentScope(Environment& env, ThreadType type, const std::string& name) : id(std::this_thread::get_id()) { threadInfoStore.registerThread(&env, type, name); } -Environment::Scope::~Scope() { +EnvironmentScope::~EnvironmentScope() { assert(id == std::this_thread::get_id()); threadInfoStore.unregisterThread(); } @@ -90,6 +91,12 @@ Environment::Environment(FileSource& fs) : id(makeEnvironmentID()), fileSource(fs), loop(uv_loop_new()) { } +Environment::~Environment() { + assert(abandonedVAOs.empty()); + assert(abandonedTextures.empty()); + assert(abandonedBuffers.empty()); +} + Environment& Environment::Get() { Environment* env = threadInfoStore.getThreadInfo().env; assert(env); @@ -129,6 +136,50 @@ void Environment::cancelRequest(Request* req) { fileSource.cancel(req); } +// ############################################################################################# + +#pragma mark - OpenGL cleanup + +void Environment::abandonVAO(uint32_t vao) { + assert(currentlyOn(ThreadType::Map)); + abandonedVAOs.emplace_back(vao); +} + +void Environment::abandonBuffer(uint32_t buffer) { + assert(currentlyOn(ThreadType::Map)); + abandonedBuffers.emplace_back(buffer); +} + +void Environment::abandonTexture(uint32_t texture) { + assert(currentlyOn(ThreadType::Map)); + abandonedTextures.emplace_back(texture); +} + +// Actually remove the objects we marked as abandoned with the above methods. +void Environment::performCleanup() { + assert(currentlyOn(ThreadType::Map)); + + if (!abandonedVAOs.empty()) { + MBGL_CHECK_ERROR(gl::DeleteVertexArrays(static_cast<GLsizei>(abandonedVAOs.size()), + abandonedVAOs.data())); + abandonedVAOs.clear(); + } + + if (!abandonedTextures.empty()) { + MBGL_CHECK_ERROR(glDeleteTextures(static_cast<GLsizei>(abandonedTextures.size()), + abandonedTextures.data())); + abandonedTextures.clear(); + } + + if (!abandonedBuffers.empty()) { + MBGL_CHECK_ERROR(glDeleteBuffers(static_cast<GLsizei>(abandonedBuffers.size()), + abandonedBuffers.data())); + abandonedBuffers.clear(); + } +} + +// ############################################################################################# + void Environment::terminate() { fileSource.abort(*this); } diff --git a/src/mbgl/map/environment.hpp b/src/mbgl/map/environment.hpp index b631abf13d..1cd33a5e6d 100644 --- a/src/mbgl/map/environment.hpp +++ b/src/mbgl/map/environment.hpp @@ -6,6 +6,7 @@ #include <thread> #include <functional> +#include <vector> typedef struct uv_loop_s uv_loop_t; @@ -25,16 +26,8 @@ enum class ThreadType : uint8_t { class Environment final : private util::noncopyable { public: - class Scope final { - public: - Scope(Environment&, ThreadType, const std::string& name); - ~Scope(); - - private: - std::thread::id id; - }; - Environment(FileSource&); + ~Environment(); static Environment& Get(); static bool inScope(); @@ -42,10 +35,27 @@ public: static std::string threadName(); unsigned getID() const; + + // ############################################################################################# + + // File request APIs void requestAsync(const Resource&, std::function<void(const Response&)>); Request* request(const Resource&, std::function<void(const Response&)>); void cancelRequest(Request*); + // ############################################################################################# + + // Mark OpenGL objects for deletion + void abandonVAO(uint32_t vao); + void abandonBuffer(uint32_t buffer); + void abandonTexture(uint32_t texture); + + // Actually remove the objects we marked as abandoned with the above methods. + // Only call this while the OpenGL context is exclusive to this thread. + void performCleanup(); + + // ############################################################################################# + // Request to terminate the environment. void terminate(); @@ -53,10 +63,24 @@ private: unsigned id; FileSource& fileSource; + // Stores OpenGL objects that we marked for deletion + std::vector<uint32_t> abandonedVAOs; + std::vector<uint32_t> abandonedBuffers; + std::vector<uint32_t> abandonedTextures; + public: uv_loop_t* const loop; }; +class EnvironmentScope final { +public: + EnvironmentScope(Environment&, ThreadType, const std::string& name); + ~EnvironmentScope(); + +private: + std::thread::id id; +}; + } #endif diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 22e6cbcebb..bc53d0d0fa 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -1,6 +1,7 @@ #include <mbgl/map/map.hpp> #include <mbgl/map/environment.hpp> #include <mbgl/map/view.hpp> +#include <mbgl/map/map_data.hpp> #include <mbgl/platform/platform.hpp> #include <mbgl/map/source.hpp> #include <mbgl/renderer/painter.hpp> @@ -61,6 +62,7 @@ using namespace mbgl; Map::Map(View& view_, FileSource& fileSource_) : env(util::make_unique<Environment>(fileSource_)), + scope(util::make_unique<EnvironmentScope>(*env, ThreadType::Main, "Main")), view(view_), transform(view_), fileSource(fileSource_), @@ -70,7 +72,8 @@ Map::Map(View& view_, FileSource& fileSource_) lineAtlas(util::make_unique<LineAtlas>(512, 512)), texturePool(std::make_shared<TexturePool>()), painter(util::make_unique<Painter>(*spriteAtlas, *glyphAtlas, *lineAtlas)), - annotationManager(util::make_unique<AnnotationManager>()) + annotationManager(util::make_unique<AnnotationManager>()), + data(util::make_unique<MapData>()) { view.initialize(this); } @@ -80,15 +83,28 @@ Map::~Map() { stop(); } + // Extend the scope to include both Main and Map thread types to ease cleanup. + scope.reset(); + scope = util::make_unique<EnvironmentScope>( + *env, static_cast<ThreadType>(static_cast<uint8_t>(ThreadType::Main) | + static_cast<uint8_t>(ThreadType::Map)), + "MapandMain"); + // Explicitly reset all pointers. activeSources.clear(); sprite.reset(); glyphStore.reset(); style.reset(); - texturePool.reset(); workers.reset(); + painter.reset(); + annotationManager.reset(); + lineAtlas.reset(); + spriteAtlas.reset(); + glyphAtlas.reset(); uv_run(env->loop, UV_RUN_DEFAULT); + + env->performCleanup(); } uv::worker &Map::getWorker() { @@ -125,11 +141,7 @@ void Map::start(bool startPaused) { }); asyncUpdate = util::make_unique<uv::async>(env->loop, [this] { - assert(Environment::currentlyOn(ThreadType::Map)); - - if (state.hasSize()) { - prepare(); - } + update(); }); asyncRender = util::make_unique<uv::async>(env->loop, [this] { @@ -162,6 +174,8 @@ void Map::start(bool startPaused) { isStopped = true; view.notify(); }); + + triggerUpdate(); } void Map::stop(std::function<void ()> callback) { @@ -233,13 +247,15 @@ void Map::run() { threadName += "andMain"; } - Environment::Scope scope(*env, threadType, threadName); + EnvironmentScope mapScope(*env, threadType, threadName); if (mode == Mode::Continuous) { checkForPause(); } - if (mode == Mode::Static && !style && styleURL.empty()) { + auto styleInfo = data->getStyleInfo(); + + if (mode == Mode::Static && !style && (styleInfo.url.empty() && styleInfo.json.empty())) { throw util::Exception("Style is not set"); } @@ -284,7 +300,9 @@ void Map::renderSync() { rendered = false; } -void Map::triggerUpdate() { +void Map::triggerUpdate(const Update u) { + updated |= static_cast<UpdateType>(u); + if (mode == Mode::Static) { prepare(); } else if (asyncUpdate) { @@ -332,36 +350,27 @@ void Map::setup() { } void Map::setStyleURL(const std::string &url) { - // TODO: Make threadsafe. - - styleURL = url; - if (mode == Mode::Continuous) { - stop(); - start(); - } -} + assert(Environment::currentlyOn(ThreadType::Main)); -void Map::setStyleJSON(std::string newStyleJSON, const std::string &base) { - // TODO: Make threadsafe. - styleJSON.swap(newStyleJSON); - sprite.reset(); - if (!style) { - style = std::make_shared<Style>(); + const size_t pos = url.rfind('/'); + std::string base = ""; + if (pos != std::string::npos) { + base = url.substr(0, pos + 1); } - style->base = base; - style->loadJSON((const uint8_t *)styleJSON.c_str()); - style->cascadeClasses(classes); - style->setDefaultTransitionDuration(defaultTransitionDuration); + data->setStyleInfo({ url, base, "" }); + triggerUpdate(Update::StyleInfo); +} - const std::string glyphURL = util::mapbox::normalizeGlyphsURL(style->glyph_url, getAccessToken()); - glyphStore->setURL(glyphURL); +void Map::setStyleJSON(const std::string& json, const std::string& base) { + assert(Environment::currentlyOn(ThreadType::Main)); - triggerUpdate(); + data->setStyleInfo({ "", base, json }); + triggerUpdate(Update::StyleInfo); } std::string Map::getStyleJSON() const { - return styleJSON; + return data->getStyleInfo().json; } util::ptr<Sprite> Map::getSprite() { @@ -522,11 +531,11 @@ void Map::stopRotating() { #pragma mark - Access Token void Map::setAccessToken(const std::string &token) { - accessToken = token; + data->setAccessToken(token); } -const std::string &Map::getAccessToken() const { - return accessToken; +std::string Map::getAccessToken() const { + return data->getAccessToken(); } #pragma mark - Annotations @@ -583,69 +592,58 @@ void Map::updateAnnotationTiles(std::vector<Tile::ID>& ids) { #pragma mark - Toggles void Map::setDebug(bool value) { - debug = value; - assert(painter); - painter->setDebug(debug); - triggerUpdate(); + data->setDebug(value); + triggerUpdate(Update::Debug); } void Map::toggleDebug() { - setDebug(!debug); + data->toggleDebug(); + triggerUpdate(Update::Debug); } bool Map::getDebug() const { - return debug; + return data->getDebug(); +} + +std::chrono::steady_clock::time_point Map::getTime() const { + return data->getAnimationTime(); } void Map::addClass(const std::string& klass) { - if (hasClass(klass)) return; - classes.push_back(klass); - if (style) { - style->cascadeClasses(classes); - if (style->hasTransitions()) { - triggerUpdate(); - } + if (data->addClass(klass)) { + triggerUpdate(Update::Classes); } } void Map::removeClass(const std::string& klass) { - if (!hasClass(klass)) return; - classes.erase(std::remove(classes.begin(), classes.end(), klass), classes.end()); - if (style) { - style->cascadeClasses(classes); - if (style->hasTransitions()) { - triggerUpdate(); - } + if (data->removeClass(klass)) { + triggerUpdate(Update::Classes); } } -void Map::setClasses(const std::vector<std::string>& classes_) { - classes = classes_; - if (style) { - style->cascadeClasses(classes); - if (style->hasTransitions()) { - triggerUpdate(); - } - } +void Map::setClasses(const std::vector<std::string>& classes) { + data->setClasses(classes); + triggerUpdate(Update::Classes); } bool Map::hasClass(const std::string& klass) const { - return std::find(classes.begin(), classes.end(), klass) != classes.end(); + return data->hasClass(klass); } std::vector<std::string> Map::getClasses() const { - return classes; + return data->getClasses(); } void Map::setDefaultTransitionDuration(std::chrono::steady_clock::duration duration) { - defaultTransitionDuration = duration; - if (style) { - style->setDefaultTransitionDuration(duration); - } + assert(Environment::currentlyOn(ThreadType::Main)); + + data->setDefaultTransitionDuration(duration); + triggerUpdate(Update::DefaultTransitionDuration); } std::chrono::steady_clock::duration Map::getDefaultTransitionDuration() { - return defaultTransitionDuration; + assert(Environment::currentlyOn(ThreadType::Main)); + return data->getDefaultTransitionDuration(); } void Map::updateSources() { @@ -657,7 +655,9 @@ void Map::updateSources() { } // Then, reenable all of those that we actually use when drawing this layer. - updateSources(style->layers); + if (style) { + updateSources(style->layers); + } // Then, construct or destroy the actual source object, depending on enabled state. for (const auto& source : activeSources) { @@ -702,45 +702,94 @@ void Map::updateTiles() { } } -void Map::prepare() { +void Map::update() { + assert(Environment::currentlyOn(ThreadType::Map)); + + if (state.hasSize()) { + prepare(); + } +} + +void Map::reloadStyle() { assert(Environment::currentlyOn(ThreadType::Map)); - if (!style) { - style = std::make_shared<Style>(); + style = std::make_shared<Style>(); - env->request({ Resource::Kind::JSON, styleURL}, [&](const Response &res) { + const auto styleInfo = data->getStyleInfo(); + + if (!styleInfo.url.empty()) { + // We have a style URL + env->request({ Resource::Kind::JSON, styleInfo.url }, [&](const Response &res) { if (res.status == Response::Successful) { - // Calculate the base - const size_t pos = styleURL.rfind('/'); - std::string base = ""; - if (pos != std::string::npos) { - base = styleURL.substr(0, pos + 1); - } - - setStyleJSON(res.data, base); + loadStyleJSON(res.data, styleInfo.base); } else { Log::Error(Event::Setup, "loading style failed: %s", res.message.c_str()); } }); + } else { + // We got JSON data directly. + loadStyleJSON(styleInfo.json, styleInfo.base); + } +} + +void Map::loadStyleJSON(const std::string& json, const std::string& base) { + assert(Environment::currentlyOn(ThreadType::Map)); + + sprite.reset(); + style = std::make_shared<Style>(); + style->base = base; + style->loadJSON((const uint8_t *)json.c_str()); + style->cascadeClasses(data->getClasses()); + style->setDefaultTransitionDuration(data->getDefaultTransitionDuration()); + + const std::string glyphURL = util::mapbox::normalizeGlyphsURL(style->glyph_url, getAccessToken()); + glyphStore->setURL(glyphURL); + + triggerUpdate(); +} + +void Map::prepare() { + assert(Environment::currentlyOn(ThreadType::Map)); + + const auto u = updated.exchange(static_cast<UpdateType>(Update::Nothing)); + if (u & static_cast<UpdateType>(Update::StyleInfo)) { + reloadStyle(); + } + if (u & static_cast<UpdateType>(Update::Debug)) { + assert(painter); + painter->setDebug(data->getDebug()); + } + if (u & static_cast<UpdateType>(Update::DefaultTransitionDuration)) { + if (style) { + style->setDefaultTransitionDuration(data->getDefaultTransitionDuration()); + } + } + if (u & static_cast<UpdateType>(Update::Classes)) { + if (style) { + style->cascadeClasses(data->getClasses()); + } } // Update transform transitions. - animationTime = std::chrono::steady_clock::now(); + + const auto animationTime = std::chrono::steady_clock::now(); + data->setAnimationTime(animationTime); if (transform.needsTransition()) { transform.updateTransitions(animationTime); } state = transform.currentState(); - animationTime = std::chrono::steady_clock::now(); - updateSources(); - style->updateProperties(state.getNormalizedZoom(), animationTime); + if (style) { + updateSources(); + style->updateProperties(state.getNormalizedZoom(), animationTime); - // Allow the sprite atlas to potentially pull new sprite images if needed. - spriteAtlas->resize(state.getPixelRatio()); - spriteAtlas->setSprite(getSprite()); + // Allow the sprite atlas to potentially pull new sprite images if needed. + spriteAtlas->resize(state.getPixelRatio()); + spriteAtlas->setSprite(getSprite()); - updateTiles(); + updateTiles(); + } if (mode == Mode::Continuous) { view.invalidate(); @@ -749,9 +798,13 @@ void Map::prepare() { void Map::render() { assert(Environment::currentlyOn(ThreadType::Map)); + + // Cleanup OpenGL objects that we abandoned since the last render call. + env->performCleanup(); + assert(painter); painter->render(*style, activeSources, - state, animationTime); + state, data->getAnimationTime()); // Schedule another rerender when we definitely need a next frame. if (transform.needsTransition() || style->hasTransitions()) { triggerUpdate(); diff --git a/src/mbgl/map/map_data.cpp b/src/mbgl/map/map_data.cpp new file mode 100644 index 0000000000..23bc094990 --- /dev/null +++ b/src/mbgl/map/map_data.cpp @@ -0,0 +1,44 @@ +#include "map_data.hpp" + +#include <algorithm> + +namespace mbgl { + +// Adds the class if it's not yet set. Returns true when it added the class, and false when it +// was already present. +bool MapData::addClass(const std::string& klass) { + Lock lock(mtx); + if (std::find(classes.begin(), classes.end(), klass) != classes.end()) return false; + classes.push_back(klass); + return true; +} + +// Removes the class if it's present. Returns true when it remvoed the class, and false when it +// was not present. +bool MapData::removeClass(const std::string& klass) { + Lock lock(mtx); + const auto it = std::find(classes.begin(), classes.end(), klass); + if (it != classes.end()) { + classes.erase(it); + return true; + } + return false; +} + +// Returns true when class is present in the list of currently set classes. +bool MapData::hasClass(const std::string& klass) const { + Lock lock(mtx); + return std::find(classes.begin(), classes.end(), klass) != classes.end(); +} + +void MapData::setClasses(const std::vector<std::string>& klasses) { + Lock lock(mtx); + classes = klasses; +} + +std::vector<std::string> MapData::getClasses() const { + Lock lock(mtx); + return classes; +} + +}
\ No newline at end of file diff --git a/src/mbgl/map/map_data.hpp b/src/mbgl/map/map_data.hpp new file mode 100644 index 0000000000..c0d57134d9 --- /dev/null +++ b/src/mbgl/map/map_data.hpp @@ -0,0 +1,102 @@ +#ifndef MBGL_MAP_MAP_DATA +#define MBGL_MAP_MAP_DATA + +#include <string> +#include <mutex> +#include <atomic> +#include <chrono> +#include <vector> + +namespace mbgl { + +struct StyleInfo { + std::string url; + std::string base; + std::string json; +}; + +class MapData { + using Lock = std::lock_guard<std::mutex>; + +public: + inline MapData() { + setAnimationTime(std::chrono::steady_clock::time_point::min()); + setDefaultTransitionDuration(std::chrono::steady_clock::duration::zero()); + } + + inline StyleInfo getStyleInfo() const { + Lock lock(mtx); + return styleInfo; + } + inline void setStyleInfo(StyleInfo&& info) { + Lock lock(mtx); + styleInfo = info; + } + + inline std::string getAccessToken() const { + Lock lock(mtx); + return accessToken; + } + inline void setAccessToken(const std::string &token) { + Lock lock(mtx); + accessToken = token; + } + + // Adds the class if it's not yet set. Returns true when it added the class, and false when it + // was already present. + bool addClass(const std::string& klass); + + // Removes the class if it's present. Returns true when it remvoed the class, and false when it + // was not present. + bool removeClass(const std::string& klass); + + // Returns true when class is present in the list of currently set classes. + bool hasClass(const std::string& klass) const; + + // Changes the list of currently set classes to the new list. + void setClasses(const std::vector<std::string>& klasses); + + // Returns a list of all currently set classes. + std::vector<std::string> getClasses() const; + + + inline bool getDebug() const { + return debug; + } + inline bool toggleDebug() { + return debug ^= 1u; + } + inline void setDebug(bool value) { + debug = value; + } + + inline std::chrono::steady_clock::time_point getAnimationTime() const { + // We're casting the time_point to and from a duration because libstdc++ + // has a bug that doesn't allow time_points to be atomic. + return std::chrono::steady_clock::time_point(animationTime); + } + inline void setAnimationTime(std::chrono::steady_clock::time_point timePoint) { + animationTime = timePoint.time_since_epoch(); + }; + + inline std::chrono::steady_clock::duration getDefaultTransitionDuration() const { + return defaultTransitionDuration; + } + inline void setDefaultTransitionDuration(std::chrono::steady_clock::duration duration) { + defaultTransitionDuration = duration; + }; + +private: + mutable std::mutex mtx; + + StyleInfo styleInfo; + std::string accessToken; + std::vector<std::string> classes; + std::atomic<uint8_t> debug { false }; + std::atomic<std::chrono::steady_clock::time_point::duration> animationTime; + std::atomic<std::chrono::steady_clock::duration> defaultTransitionDuration; +}; + +} + +#endif diff --git a/src/mbgl/map/tile_data.cpp b/src/mbgl/map/tile_data.cpp index aed182671b..1832bd8f0c 100644 --- a/src/mbgl/map/tile_data.cpp +++ b/src/mbgl/map/tile_data.cpp @@ -97,7 +97,7 @@ void TileData::reparse(uv::worker& worker, std::function<void()> callback) new uv::work<util::ptr<TileData>>( worker, [this](util::ptr<TileData>& tile) { - Environment::Scope scope(env, ThreadType::TileWorker, "TileWorker_" + tile->name); + EnvironmentScope scope(env, ThreadType::TileWorker, "TileWorker_" + tile->name); tile->parse(); }, [callback](util::ptr<TileData>&) { diff --git a/src/mbgl/util/texture_pool.cpp b/src/mbgl/util/texture_pool.cpp index 33bca01c05..845796f5df 100644 --- a/src/mbgl/util/texture_pool.cpp +++ b/src/mbgl/util/texture_pool.cpp @@ -1,4 +1,5 @@ #include <mbgl/util/texture_pool.hpp> +#include <mbgl/map/environment.hpp> #include <vector> @@ -42,17 +43,9 @@ void TexturePool::removeTextureID(GLuint texture_id) { } void TexturePool::clearTextureIDs() { - std::vector<GLuint> ids_to_remove; - ids_to_remove.reserve(texture_ids.size()); - - for (std::set<GLuint>::iterator id_iterator = texture_ids.begin(); - id_iterator != texture_ids.end(); ++id_iterator) { - ids_to_remove.push_back(*id_iterator); - } - - if (!ids_to_remove.empty()) { - MBGL_CHECK_ERROR(glDeleteTextures((GLsizei)ids_to_remove.size(), &ids_to_remove[0])); + auto& env = Environment::Get(); + for (auto texture : texture_ids) { + env.abandonTexture(texture); } - texture_ids.clear(); } |