diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2015-05-28 13:50:47 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2015-06-01 13:22:02 -0700 |
commit | ec06bb7e3cb1858b2f79f8826a9f1e923fdbaf24 (patch) | |
tree | 628c6e76d55ada790206dc5750866d51eb53d474 /src | |
parent | d2f710564994e902cab400caffbd46a0cddb57c2 (diff) | |
download | qtlocation-mapboxgl-ec06bb7e3cb1858b2f79f8826a9f1e923fdbaf24.tar.gz |
Merge ResourceLoader into Style and move atlas ownership
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/map/map_context.cpp | 38 | ||||
-rw-r--r-- | src/mbgl/map/map_context.hpp | 14 | ||||
-rw-r--r-- | src/mbgl/map/resource_loader.cpp | 160 | ||||
-rw-r--r-- | src/mbgl/map/resource_loader.hpp | 91 | ||||
-rw-r--r-- | src/mbgl/renderer/painter.cpp | 22 | ||||
-rw-r--r-- | src/mbgl/renderer/painter.hpp | 8 | ||||
-rw-r--r-- | src/mbgl/renderer/painter_fill.cpp | 6 | ||||
-rw-r--r-- | src/mbgl/renderer/painter_line.cpp | 14 | ||||
-rw-r--r-- | src/mbgl/renderer/painter_symbol.cpp | 10 | ||||
-rw-r--r-- | src/mbgl/style/style.cpp | 183 | ||||
-rw-r--r-- | src/mbgl/style/style.hpp | 66 |
11 files changed, 242 insertions, 370 deletions
diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index c8948097f7..a834f50655 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -2,19 +2,12 @@ #include <mbgl/map/map_data.hpp> #include <mbgl/map/view.hpp> #include <mbgl/map/environment.hpp> -#include <mbgl/map/source.hpp> #include <mbgl/map/still_image.hpp> #include <mbgl/platform/log.hpp> #include <mbgl/renderer/painter.hpp> -#include <mbgl/text/glyph_store.hpp> - -#include <mbgl/geometry/glyph_atlas.hpp> -#include <mbgl/geometry/sprite_atlas.hpp> -#include <mbgl/geometry/line_atlas.hpp> - #include <mbgl/storage/resource.hpp> #include <mbgl/storage/response.hpp> @@ -34,10 +27,6 @@ MapContext::MapContext(uv_loop_t* loop, View& view_, FileSource& fileSource, Map envScope(env, ThreadType::Map, "Map"), updated(static_cast<UpdateType>(Update::Nothing)), asyncUpdate(std::make_unique<uv::async>(loop, [this] { update(); })), - glyphStore(std::make_unique<GlyphStore>(loop, env)), - glyphAtlas(std::make_unique<GlyphAtlas>(1024, 1024)), - spriteAtlas(std::make_unique<SpriteAtlas>(512, 512)), - lineAtlas(std::make_unique<LineAtlas>(512, 512)), texturePool(std::make_unique<TexturePool>()) { assert(Environment::currentlyOn(ThreadType::Map)); @@ -51,14 +40,9 @@ MapContext::~MapContext() { // Explicit resets currently necessary because these abandon resources that need to be // cleaned up by env.performCleanup(); - resourceLoader.reset(); style.reset(); painter.reset(); texturePool.reset(); - lineAtlas.reset(); - spriteAtlas.reset(); - glyphAtlas.reset(); - glyphStore.reset(); env.performCleanup(); @@ -116,21 +100,11 @@ void MapContext::setStyleJSON(const std::string& json, const std::string& base) void MapContext::loadStyleJSON(const std::string& json, const std::string& base) { assert(Environment::currentlyOn(ThreadType::Map)); - resourceLoader.reset(); style.reset(); - - style = std::make_unique<Style>(); - style->base = base; - style->loadJSON((const uint8_t *)json.c_str()); + style = std::make_unique<Style>(json, base, asyncUpdate->get()->loop, env); style->cascade(data.getClasses()); style->setDefaultTransitionDuration(data.getDefaultTransitionDuration()); - - glyphStore->setURL(style->glyph_url); - - resourceLoader = std::make_unique<ResourceLoader>(); - resourceLoader->setObserver(this); - resourceLoader->setStyle(style.get()); - resourceLoader->setGlyphStore(glyphStore.get()); + style->setObserver(this); triggerUpdate(Update::Zoom); } @@ -138,7 +112,7 @@ void MapContext::loadStyleJSON(const std::string& json, const std::string& base) void MapContext::updateTiles() { assert(Environment::currentlyOn(ThreadType::Map)); - resourceLoader->update(data, transformState, *glyphAtlas, *spriteAtlas, *texturePool); + style->update(data, transformState, *texturePool); } void MapContext::updateAnnotationTiles(const std::vector<TileID>& ids) { @@ -177,7 +151,7 @@ void MapContext::update() { updateTiles(); - if (style->isLoaded() && resourceLoader->getSprite()->isLoaded()) { + if (style->isLoaded()) { if (!data.getFullyLoaded()) { data.setFullyLoaded(true); } @@ -220,7 +194,7 @@ void MapContext::render() { assert(style); if (!painter) { - painter = std::make_unique<Painter>(*spriteAtlas, *glyphAtlas, *lineAtlas); + painter = std::make_unique<Painter>(); painter->setup(); } @@ -240,7 +214,7 @@ void MapContext::render() { double MapContext::getTopOffsetPixelsForAnnotationSymbol(const std::string& symbol) { assert(Environment::currentlyOn(ThreadType::Map)); - const SpritePosition pos = resourceLoader->getSprite()->getSpritePosition(symbol); + const SpritePosition pos = style->sprite->getSpritePosition(symbol); return -pos.height / pos.pixelRatio / 2; } diff --git a/src/mbgl/map/map_context.hpp b/src/mbgl/map/map_context.hpp index fb9fdb4d4b..d19c95a3bd 100644 --- a/src/mbgl/map/map_context.hpp +++ b/src/mbgl/map/map_context.hpp @@ -4,8 +4,8 @@ #include <mbgl/map/tile_id.hpp> #include <mbgl/map/update.hpp> #include <mbgl/map/environment.hpp> -#include <mbgl/map/resource_loader.hpp> #include <mbgl/map/transform_state.hpp> +#include <mbgl/style/style.hpp> #include <mbgl/util/ptr.hpp> #include <vector> @@ -20,20 +20,15 @@ namespace mbgl { class View; class MapData; -class GlyphStore; -class GlyphAtlas; -class SpriteAtlas; -class LineAtlas; class TexturePool; class Painter; class Sprite; -class Style; class Worker; class StillImage; struct LatLng; struct LatLngBounds; -class MapContext : public ResourceLoader::Observer { +class MapContext : public Style::Observer { public: MapContext(uv_loop_t*, View&, FileSource&, MapData&); ~MapContext(); @@ -81,14 +76,9 @@ private: UpdateType updated { static_cast<UpdateType>(Update::Nothing) }; std::unique_ptr<uv::async> asyncUpdate; - std::unique_ptr<GlyphStore> glyphStore; - std::unique_ptr<GlyphAtlas> glyphAtlas; - std::unique_ptr<SpriteAtlas> spriteAtlas; - std::unique_ptr<LineAtlas> lineAtlas; std::unique_ptr<TexturePool> texturePool; std::unique_ptr<Painter> painter; std::unique_ptr<Style> style; - std::unique_ptr<ResourceLoader> resourceLoader; std::string styleURL; std::string styleJSON; diff --git a/src/mbgl/map/resource_loader.cpp b/src/mbgl/map/resource_loader.cpp deleted file mode 100644 index 8e054c0d82..0000000000 --- a/src/mbgl/map/resource_loader.cpp +++ /dev/null @@ -1,160 +0,0 @@ -#include <mbgl/map/resource_loader.hpp> - -#include <mbgl/geometry/sprite_atlas.hpp> -#include <mbgl/map/environment.hpp> -#include <mbgl/map/source.hpp> -#include <mbgl/map/sprite.hpp> -#include <mbgl/map/transform.hpp> -#include <mbgl/style/style.hpp> - -#include <cassert> - -namespace mbgl { - -ResourceLoader::ResourceLoader() { - assert(Environment::currentlyOn(ThreadType::Map)); -} - -ResourceLoader::~ResourceLoader() { - assert(Environment::currentlyOn(ThreadType::Map)); - - for (const auto& source : style_->sources) { - source->setObserver(nullptr); - } - - if (sprite_) { - sprite_->setObserver(nullptr); - } - - if (glyphStore_) { - glyphStore_->setObserver(nullptr); - } -} - -void ResourceLoader::setObserver(Observer* observer) { - assert(Environment::currentlyOn(ThreadType::Map)); - assert(!observer_); - - observer_ = observer; -} - -void ResourceLoader::setStyle(Style* style) { - assert(style); - - style_ = style; - - for (const auto& source : style->sources) { - source->setObserver(this); - source->load(); - } -} - -void ResourceLoader::setGlyphStore(GlyphStore* glyphStore) { - assert(glyphStore); - - if (glyphStore_) { - glyphStore_->setObserver(nullptr); - } - - glyphStore_ = glyphStore; - glyphStore_->setObserver(this); -} - -void ResourceLoader::update(MapData& data, - const TransformState& transform, - GlyphAtlas& glyphAtlas, - SpriteAtlas& spriteAtlas, - TexturePool& texturePool) { - if (!style_) { - return; - } - - const float pixelRatio = transform.getPixelRatio(); - if (!sprite_ || !sprite_->hasPixelRatio(pixelRatio)) { - sprite_ = std::make_unique<Sprite>(style_->getSpriteURL(), pixelRatio); - sprite_->setObserver(this); - - spriteAtlas.resize(pixelRatio); - spriteAtlas.setSprite(sprite_); - } - - bool allTilesUpdated = true; - for (const auto& source : style_->sources) { - if (!source->update(data, transform, *style_, glyphAtlas, *glyphStore_, - spriteAtlas, sprite_, texturePool, shouldReparsePartialTiles_)) { - allTilesUpdated = false; - } - } - - // We can only stop updating "partial" tiles when all of them - // were notified of the arrival of the new resources. - if (allTilesUpdated) { - shouldReparsePartialTiles_ = false; - } -} - -void ResourceLoader::onGlyphRangeLoaded() { - shouldReparsePartialTiles_ = true; - - emitTileDataChanged(); -} - -void ResourceLoader::onGlyphRangeLoadingFailed(std::exception_ptr error) { - emitResourceLoadingFailed(error); -} - -void ResourceLoader::onSourceLoaded() { - emitTileDataChanged(); -} - -void ResourceLoader::onSourceLoadingFailed(std::exception_ptr error) { - emitResourceLoadingFailed(error); -} - -void ResourceLoader::onTileLoaded(bool isNewTile) { - if (isNewTile) { - shouldReparsePartialTiles_ = true; - } - - emitTileDataChanged(); -} - -void ResourceLoader::onTileLoadingFailed(std::exception_ptr error) { - emitResourceLoadingFailed(error); -} - -void ResourceLoader::onSpriteLoaded() { - shouldReparsePartialTiles_ = true; - - emitTileDataChanged(); -} - -void ResourceLoader::onSpriteLoadingFailed(std::exception_ptr error) { - emitResourceLoadingFailed(error); -} - -void ResourceLoader::emitTileDataChanged() { - assert(Environment::currentlyOn(ThreadType::Map)); - - if (observer_) { - observer_->onTileDataChanged(); - } -} - -void ResourceLoader::emitResourceLoadingFailed(std::exception_ptr error) { - assert(Environment::currentlyOn(ThreadType::Map)); - - try { - if (error) { - std::rethrow_exception(error); - } - } catch(const std::exception& e) { - Log::Error(Event::ResourceLoader, e.what()); - } - - if (observer_) { - observer_->onResourceLoadingFailed(error); - } -} - -} diff --git a/src/mbgl/map/resource_loader.hpp b/src/mbgl/map/resource_loader.hpp deleted file mode 100644 index 525e4653a0..0000000000 --- a/src/mbgl/map/resource_loader.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef MBGL_MAP_RESOURCE_LOADER -#define MBGL_MAP_RESOURCE_LOADER - -#include <mbgl/map/source.hpp> -#include <mbgl/map/sprite.hpp> -#include <mbgl/text/glyph_store.hpp> -#include <mbgl/util/noncopyable.hpp> - -#include <string> - -namespace mbgl { - -class GlyphAtlas; -class GlyphStore; -class MapData; -class SpriteAtlas; -class Style; -class TexturePool; -class TransformState; - -// ResourceLoader is responsible for loading and updating the Source(s) owned -// by the Style. The Source object currently owns all the tiles, thus this -// class will notify its observers of any change on these tiles which will -// ultimately cause a new rendering to be triggered. -class ResourceLoader : public GlyphStore::Observer, - public Source::Observer, - public Sprite::Observer, - private util::noncopyable { -public: - class Observer { - public: - virtual ~Observer() = default; - - virtual void onTileDataChanged() = 0; - virtual void onResourceLoadingFailed(std::exception_ptr error) = 0; - }; - - ResourceLoader(); - ~ResourceLoader(); - - void setObserver(Observer* observer); - - // The style object currently owns all the sources. When setting - // a new style we will go through all of them and try to load. - void setStyle(Style* style); - - // TODO: Move GlyphStore to ResourceLoader. We cannot do it now - // because we reset the ResourceLoader every time we change the - // style. - void setGlyphStore(GlyphStore* glyphStore); - - // Fetch the tiles needed by the current viewport and emit a signal when - // a tile is ready so observers can render the tile. - void update(MapData&, const TransformState&, GlyphAtlas&, SpriteAtlas&, TexturePool&); - - // FIXME: There is probably a better place for this. - inline util::ptr<Sprite> getSprite() const { - return sprite_; - } - - // GlyphStore::Observer implementation. - void onGlyphRangeLoaded() override; - void onGlyphRangeLoadingFailed(std::exception_ptr error) override; - - // Source::Observer implementation. - void onSourceLoaded() override; - void onSourceLoadingFailed(std::exception_ptr error) override; - void onTileLoaded(bool isNewTile) override; - void onTileLoadingFailed(std::exception_ptr error) override; - - // Sprite::Observer implementation. - void onSpriteLoaded() override; - void onSpriteLoadingFailed(std::exception_ptr error) override; - -private: - void emitTileDataChanged(); - void emitResourceLoadingFailed(std::exception_ptr error); - - bool shouldReparsePartialTiles_ = false; - - util::ptr<Sprite> sprite_; - - GlyphStore* glyphStore_ = nullptr; - Style* style_ = nullptr; - - Observer* observer_ = nullptr; -}; - -} - -#endif diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index a8e420215f..bad4f9085a 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -41,11 +41,7 @@ using namespace mbgl; #define BUFFER_OFFSET(i) ((char *)nullptr + (i)) -Painter::Painter(SpriteAtlas& spriteAtlas_, GlyphAtlas& glyphAtlas_, LineAtlas& lineAtlas_) - : spriteAtlas(spriteAtlas_) - , glyphAtlas(glyphAtlas_) - , lineAtlas(lineAtlas_) -{ +Painter::Painter() { } Painter::~Painter() { @@ -171,6 +167,10 @@ void Painter::prepareTile(const Tile& tile) { void Painter::render(const Style& style, TransformState state_, TimePoint time) { state = state_; + glyphAtlas = style.glyphAtlas.get(); + spriteAtlas = style.spriteAtlas.get(); + lineAtlas = style.lineAtlas.get(); + std::set<Source*> sources; for (const auto& source : style.sources) { if (source->enabled) { @@ -191,9 +191,9 @@ void Painter::render(const Style& style, TransformState state_, TimePoint time) tileStencilBuffer.upload(); tileBorderBuffer.upload(); - spriteAtlas.upload(); - lineAtlas.upload(); - glyphAtlas.upload(); + spriteAtlas->upload(); + lineAtlas->upload(); + glyphAtlas->upload(); for (const auto& item : order) { if (item.bucket && item.bucket->needsUpload()) { @@ -389,8 +389,8 @@ void Painter::renderBackground(const StyleLayer &layer_desc) { if ((properties.opacity >= 1.0f) != (pass == RenderPass::Opaque)) return; - SpriteAtlasPosition imagePosA = spriteAtlas.getPosition(properties.image.from, true); - SpriteAtlasPosition imagePosB = spriteAtlas.getPosition(properties.image.to, true); + SpriteAtlasPosition imagePosA = spriteAtlas->getPosition(properties.image.from, true); + SpriteAtlasPosition imagePosB = spriteAtlas->getPosition(properties.image.to, true); float zoomFraction = state.getZoomFraction(); useProgram(patternShader->program); @@ -439,7 +439,7 @@ void Painter::renderBackground(const StyleLayer &layer_desc) { backgroundBuffer.bind(); patternShader->bind(0); - spriteAtlas.bind(true); + spriteAtlas->bind(true); } else { Color color = properties.color; color[0] *= properties.opacity; diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index 871612ef43..7b7bf693f4 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -78,7 +78,7 @@ struct RenderItem { class Painter : private util::noncopyable { public: - Painter(SpriteAtlas&, GlyphAtlas&, LineAtlas&); + Painter(); ~Painter(); void setup(); @@ -204,9 +204,9 @@ private: public: FrameHistory frameHistory; - SpriteAtlas& spriteAtlas; - GlyphAtlas& glyphAtlas; - LineAtlas& lineAtlas; + SpriteAtlas* spriteAtlas; + GlyphAtlas* glyphAtlas; + LineAtlas* lineAtlas; std::unique_ptr<PlainShader> plainShader; std::unique_ptr<OutlineShader> outlineShader; diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp index 64dc3d2f0a..86cef7d60e 100644 --- a/src/mbgl/renderer/painter_fill.cpp +++ b/src/mbgl/renderer/painter_fill.cpp @@ -63,8 +63,8 @@ void Painter::renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const // Image fill. if (pass == RenderPass::Translucent) { - const SpriteAtlasPosition posA = spriteAtlas.getPosition(properties.image.from, true); - const SpriteAtlasPosition posB = spriteAtlas.getPosition(properties.image.to, true); + const SpriteAtlasPosition posA = spriteAtlas->getPosition(properties.image.from, true); + const SpriteAtlasPosition posB = spriteAtlas->getPosition(properties.image.to, true); float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z); mat3 patternMatrixA; @@ -91,7 +91,7 @@ void Painter::renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const patternShader->u_patternmatrix_b = patternMatrixB; MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0)); - spriteAtlas.bind(true); + spriteAtlas->bind(true); // Draw the actual triangles into the color & stencil buffer. config.depthMask = GL_TRUE; diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp index f552ea6c43..d3949df5b9 100644 --- a/src/mbgl/renderer/painter_line.cpp +++ b/src/mbgl/renderer/painter_line.cpp @@ -66,9 +66,9 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const linesdfShader->u_blur = blur; linesdfShader->u_color = color; - LinePatternPos posA = lineAtlas.getDashPosition(properties.dash_array.from, layout.cap == CapType::Round); - LinePatternPos posB = lineAtlas.getDashPosition(properties.dash_array.to, layout.cap == CapType::Round); - lineAtlas.bind(); + LinePatternPos posA = lineAtlas->getDashPosition(properties.dash_array.from, layout.cap == CapType::Round); + LinePatternPos posB = lineAtlas->getDashPosition(properties.dash_array.to, layout.cap == CapType::Round); + lineAtlas->bind(); float patternratio = std::pow(2.0, std::floor(std::log2(state.getScale())) - id.z) / 8.0; float scaleXA = patternratio / posA.width / properties.dash_line_width / properties.dash_array.fromScale; @@ -81,14 +81,14 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const linesdfShader->u_patternscale_b = {{ scaleXB, scaleYB }}; linesdfShader->u_tex_y_b = posB.y; linesdfShader->u_image = 0; - linesdfShader->u_sdfgamma = lineAtlas.width / (properties.dash_line_width * std::min(posA.width, posB.width) * 256.0 * state.getPixelRatio()) / 2; + linesdfShader->u_sdfgamma = lineAtlas->width / (properties.dash_line_width * std::min(posA.width, posB.width) * 256.0 * state.getPixelRatio()) / 2; linesdfShader->u_mix = properties.dash_array.t; bucket.drawLineSDF(*linesdfShader); } else if (properties.image.from.size()) { - SpriteAtlasPosition imagePosA = spriteAtlas.getPosition(properties.image.from, true); - SpriteAtlasPosition imagePosB = spriteAtlas.getPosition(properties.image.to, true); + SpriteAtlasPosition imagePosA = spriteAtlas->getPosition(properties.image.from, true); + SpriteAtlasPosition imagePosB = spriteAtlas->getPosition(properties.image.to, true); float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z); @@ -110,7 +110,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const linepatternShader->u_opacity = properties.opacity; MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0)); - spriteAtlas.bind(true); + spriteAtlas->bind(true); config.depthRange = { strata + strata_epsilon, 1.0f }; // may or may not matter bucket.drawLinePatterns(*linepatternShader); diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp index 1841f2bc98..0c2f0c3cd1 100644 --- a/src/mbgl/renderer/painter_symbol.cpp +++ b/src/mbgl/renderer/painter_symbol.cpp @@ -138,7 +138,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c const float fontSize = properties.icon.size != 0 ? properties.icon.size : layout.icon.max_size; const float fontScale = fontSize / 1.0f; - spriteAtlas.bind(state.isChanging() || layout.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf); + spriteAtlas->bind(state.isChanging() || layout.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf); if (sdf) { renderSDF(bucket, @@ -147,7 +147,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c layout.icon, properties.icon, 1.0f, - {{ float(spriteAtlas.getWidth()) / 4.0f, float(spriteAtlas.getHeight()) / 4.0f }}, + {{ float(spriteAtlas->getWidth()) / 4.0f, float(spriteAtlas->getHeight()) / 4.0f }}, *sdfIconShader, &SymbolBucket::drawIcons); } else { @@ -165,7 +165,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c useProgram(iconShader->program); iconShader->u_matrix = vtxMatrix; iconShader->u_exmatrix = exMatrix; - iconShader->u_texsize = {{ float(spriteAtlas.getWidth()) / 4.0f, float(spriteAtlas.getHeight()) / 4.0f }}; + iconShader->u_texsize = {{ float(spriteAtlas->getWidth()) / 4.0f, float(spriteAtlas->getHeight()) / 4.0f }}; // Convert the -pi..pi to an int8 range. const float angle = std::round(state.getAngle() / M_PI * 128); @@ -192,7 +192,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c } if (bucket.hasTextData()) { - glyphAtlas.bind(); + glyphAtlas->bind(); renderSDF(bucket, id, @@ -200,7 +200,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c layout.text, properties.text, 24.0f, - {{ float(glyphAtlas.width) / 4, float(glyphAtlas.height) / 4 }}, + {{ float(glyphAtlas->width) / 4, float(glyphAtlas->height) / 4 }}, *sdfGlyphShader, &SymbolBucket::drawGlyphs); } diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 0acf66eb56..520cd12a70 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -1,9 +1,13 @@ #include <mbgl/style/style.hpp> #include <mbgl/map/sprite.hpp> #include <mbgl/map/source.hpp> +#include <mbgl/map/transform_state.hpp> #include <mbgl/style/style_layer.hpp> #include <mbgl/style/style_parser.hpp> #include <mbgl/style/style_bucket.hpp> +#include <mbgl/geometry/glyph_atlas.hpp> +#include <mbgl/geometry/sprite_atlas.hpp> +#include <mbgl/geometry/line_atlas.hpp> #include <mbgl/util/constants.hpp> #include <mbgl/util/uv_detail.hpp> #include <mbgl/platform/log.hpp> @@ -15,15 +19,79 @@ namespace mbgl { -Style::Style() - : mtx(std::make_unique<uv::rwlock>()), +Style::Style(const std::string& data, const std::string& base_, + uv_loop_t* loop, Environment& env) + : glyphStore(std::make_unique<GlyphStore>(loop, env)), + glyphAtlas(std::make_unique<GlyphAtlas>(1024, 1024)), + spriteAtlas(std::make_unique<SpriteAtlas>(512, 512)), + lineAtlas(std::make_unique<LineAtlas>(512, 512)), + base(base_), + mtx(std::make_unique<uv::rwlock>()), workers(4) { + + rapidjson::Document doc; + doc.Parse<0>((const char *const)data.c_str()); + if (doc.HasParseError()) { + Log::Error(Event::ParseStyle, "Error parsing style JSON at %i: %s", doc.GetErrorOffset(), doc.GetParseError()); + return; + } + + StyleParser parser; + parser.parse(doc); + + sources = parser.getSources(); + layers = parser.getLayers(); + + sprite_url = parser.getSprite(); + glyph_url = parser.getGlyphURL(); + glyphStore->setURL(glyph_url); + + for (const auto& source : sources) { + source->setObserver(this); + source->load(); + } + + glyphStore->setObserver(this); } -// Note: This constructor is seemingly empty, but we need to declare it anyway -// because this file includes uv_detail.hpp, which has the declarations necessary -// for deleting the std::unique_ptr<uv::rwlock>. -Style::~Style() {} +Style::~Style() { + for (const auto& source : sources) { + source->setObserver(nullptr); + } + + glyphStore->setObserver(nullptr); + + if (sprite) { + sprite->setObserver(nullptr); + } +} + +void Style::update(MapData& data, + const TransformState& transform, + TexturePool& texturePool) { + const float pixelRatio = transform.getPixelRatio(); + if (!sprite || !sprite->hasPixelRatio(pixelRatio)) { + sprite = std::make_unique<Sprite>(sprite_url, pixelRatio); + sprite->setObserver(this); + + spriteAtlas->resize(pixelRatio); + spriteAtlas->setSprite(sprite); + } + + bool allTilesUpdated = true; + for (const auto& source : sources) { + if (!source->update(data, transform, *this, *glyphAtlas, *glyphStore, + *spriteAtlas, sprite, texturePool, shouldReparsePartialTiles)) { + allTilesUpdated = false; + } + } + + // We can only stop updating "partial" tiles when all of them + // were notified of the arrival of the new resources. + if (allTilesUpdated) { + shouldReparsePartialTiles = false; + } +} void Style::cascade(const std::vector<std::string>& classes) { TimePoint now = Clock::now(); @@ -50,10 +118,6 @@ void Style::recalculate(float z, TimePoint now) { } } -const std::string &Style::getSpriteURL() const { - return sprite_url; -} - void Style::setDefaultTransitionDuration(Duration duration) { defaultTransition.duration = duration; } @@ -67,44 +131,89 @@ bool Style::hasTransitions() const { return false; } -void Style::loadJSON(const uint8_t *const data) { - uv::writelock lock(mtx); +bool Style::isLoaded() const { + for (const auto& source : sources) { + if (!source->isLoaded()) { + return false; + } + } - rapidjson::Document doc; - doc.Parse<0>((const char *const)data); - if (doc.HasParseError()) { - Log::Error(Event::ParseStyle, "Error parsing style JSON at %i: %s", doc.GetErrorOffset(), doc.GetParseError()); - return; + if (sprite && !sprite->isLoaded()) { + return false; } - StyleParser parser; - parser.parse(doc); + return true; +} - sources = parser.getSources(); - layers = parser.getLayers(); - sprite_url = parser.getSprite(); - glyph_url = parser.getGlyphURL(); - loaded = true; +void Style::setObserver(Observer* observer_) { + assert(Environment::currentlyOn(ThreadType::Map)); + assert(!observer); + + observer = observer_; } -bool Style::isLoaded() const { - // TODO: move loading into Style - if (!loaded) { - return false; +void Style::onGlyphRangeLoaded() { + shouldReparsePartialTiles = true; + + emitTileDataChanged(); +} + +void Style::onGlyphRangeLoadingFailed(std::exception_ptr error) { + emitResourceLoadingFailed(error); +} + +void Style::onSourceLoaded() { + emitTileDataChanged(); +} + +void Style::onSourceLoadingFailed(std::exception_ptr error) { + emitResourceLoadingFailed(error); +} + +void Style::onTileLoaded(bool isNewTile) { + if (isNewTile) { + shouldReparsePartialTiles = true; } - for (const auto& source : sources) { - if (!source->isLoaded()) { - return false; - } + emitTileDataChanged(); +} + +void Style::onTileLoadingFailed(std::exception_ptr error) { + emitResourceLoadingFailed(error); +} + +void Style::onSpriteLoaded() { + shouldReparsePartialTiles = true; + + emitTileDataChanged(); +} + +void Style::onSpriteLoadingFailed(std::exception_ptr error) { + emitResourceLoadingFailed(error); +} + +void Style::emitTileDataChanged() { + assert(Environment::currentlyOn(ThreadType::Map)); + + if (observer) { + observer->onTileDataChanged(); } +} - // TODO: move sprite into Style -// if (sprite && !sprite.isLoaded()) { -// return false; -// } +void Style::emitResourceLoadingFailed(std::exception_ptr error) { + assert(Environment::currentlyOn(ThreadType::Map)); - return true; + try { + if (error) { + std::rethrow_exception(error); + } + } catch(const std::exception& e) { + Log::Error(Event::ResourceLoader, e.what()); + } + + if (observer) { + observer->onResourceLoadingFailed(error); + } } } diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp index 42d7b0b9a0..1c70e352e8 100644 --- a/src/mbgl/style/style.hpp +++ b/src/mbgl/style/style.hpp @@ -4,6 +4,10 @@ #include <mbgl/style/property_transition.hpp> #include <mbgl/style/zoom_history.hpp> +#include <mbgl/map/source.hpp> +#include <mbgl/map/sprite.hpp> +#include <mbgl/text/glyph_store.hpp> + #include <mbgl/util/uv.hpp> #include <mbgl/util/ptr.hpp> #include <mbgl/util/noncopyable.hpp> @@ -16,33 +20,79 @@ namespace mbgl { -class Source; +class Environment; +class GlyphAtlas; +class GlyphStore; +class SpriteAtlas; +class LineAtlas; class StyleLayer; -class Style : public util::noncopyable { +class Style : public GlyphStore::Observer, + public Source::Observer, + public Sprite::Observer, + public util::noncopyable { public: - Style(); + Style(const std::string& data, + const std::string& base, + uv_loop_t*, Environment&); ~Style(); - void loadJSON(const uint8_t *const data); + class Observer { + public: + virtual ~Observer() = default; + + virtual void onTileDataChanged() = 0; + virtual void onResourceLoadingFailed(std::exception_ptr error) = 0; + }; + + void setObserver(Observer*); + bool isLoaded() const; + // Fetch the tiles needed by the current viewport and emit a signal when + // a tile is ready so observers can render the tile. + void update(MapData&, const TransformState&, TexturePool&); + void cascade(const std::vector<std::string>&); void recalculate(float z, TimePoint now); void setDefaultTransitionDuration(Duration); bool hasTransitions() const; - const std::string &getSpriteURL() const; + std::unique_ptr<GlyphStore> glyphStore; + std::unique_ptr<GlyphAtlas> glyphAtlas; + util::ptr<Sprite> sprite; + std::unique_ptr<SpriteAtlas> spriteAtlas; + std::unique_ptr<LineAtlas> lineAtlas; std::vector<util::ptr<Source>> sources; std::vector<util::ptr<StyleLayer>> layers; - std::string glyph_url; - std::string base; private: - bool loaded = false; + // GlyphStore::Observer implementation. + void onGlyphRangeLoaded() override; + void onGlyphRangeLoadingFailed(std::exception_ptr error) override; + + // Source::Observer implementation. + void onSourceLoaded() override; + void onSourceLoadingFailed(std::exception_ptr error) override; + void onTileLoaded(bool isNewTile) override; + void onTileLoadingFailed(std::exception_ptr error) override; + + // Sprite::Observer implementation. + void onSpriteLoaded() override; + void onSpriteLoadingFailed(std::exception_ptr error) override; + + void emitTileDataChanged(); + void emitResourceLoadingFailed(std::exception_ptr error); + + bool shouldReparsePartialTiles = false; + + Observer* observer = nullptr; + + std::string base; std::string sprite_url; + std::string glyph_url; PropertyTransition defaultTransition; std::unique_ptr<uv::rwlock> mtx; ZoomHistory zoomHistory; |