diff options
author | Chris Loer <chris.loer@gmail.com> | 2017-11-09 13:24:43 -0800 |
---|---|---|
committer | Chris Loer <chris.loer@mapbox.com> | 2017-11-17 10:05:15 -0800 |
commit | c0cb210ddca1901a956cd68e9142b7fb04183248 (patch) | |
tree | 7a6d5dc3d79720b930d5669d16d5912239fcc344 /src/mbgl/renderer/renderer_impl.cpp | |
parent | 9a5b2fdfc362e7041a10d5066161b51aedbb0a31 (diff) | |
download | qtlocation-mapboxgl-c0cb210ddca1901a956cd68e9142b7fb04183248.tar.gz |
[core] Switch from background to foreground placement
- Background placement code now just generates static symbol buffers
- Don't render GeometryTiles until their symbols are loaded. This is necessary for the CrossTileSymbolIndex to successfully prevent flicker.
- SymbolInstances are transferred to SymbolBucket for use on foreground during collision detection
- Symbols are sorted on foreground by sorting their index buffer but leaving vertex buffers intact (only works within one segment)
- Vertical glyphs are generated at same time as horizontal glyphs. `reprojectLineLabels` chooses which one to use at render time and hides the other.
- Icons are now always represented with a single collision box, even if they're placed along a line (this means their rotation alignment may be wrong, but the approach of representing them with multiple collision boxes wasn't very accurate either).
- Generate vertices for new debug collision boxes and collision circles
- Only add symbols within tile boundaries (reduces work, avoids double-draw)
- Update symbol_projection.cpp to support line label projection calls from CollisionIndex.
Diffstat (limited to 'src/mbgl/renderer/renderer_impl.cpp')
-rw-r--r-- | src/mbgl/renderer/renderer_impl.cpp | 74 |
1 files changed, 50 insertions, 24 deletions
diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 5987e69374..7cc92f6d7d 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -23,6 +23,7 @@ #include <mbgl/style/source_impl.hpp> #include <mbgl/style/transition_options.hpp> #include <mbgl/text/glyph_manager.hpp> +#include <mbgl/text/cross_tile_symbol_index.hpp> #include <mbgl/tile/tile.hpp> #include <mbgl/util/math.hpp> #include <mbgl/util/string.hpp> @@ -56,7 +57,9 @@ Renderer::Impl::Impl(RendererBackend& backend_, , imageImpls(makeMutable<std::vector<Immutable<style::Image::Impl>>>()) , sourceImpls(makeMutable<std::vector<Immutable<style::Source::Impl>>>()) , layerImpls(makeMutable<std::vector<Immutable<style::Layer::Impl>>>()) - , renderLight(makeMutable<Light::Impl>()) { + , renderLight(makeMutable<Light::Impl>()) + , crossTileSymbolIndex(std::make_unique<CrossTileSymbolIndex>()) + , placement(std::make_unique<Placement>(TransformState{}, MapMode::Still)) { glyphManager->setObserver(this); } @@ -348,26 +351,6 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { continue; } - // We're not clipping symbol layers, so when we have both parents and children of symbol - // layers, we drop all children in favor of their parent to avoid duplicate labels. - // See https://github.com/mapbox/mapbox-gl-native/issues/2482 - if (symbolLayer) { - bool skip = false; - // Look back through the buckets we decided to render to find out whether there is - // already a bucket from this layer that is a parent of this tile. Tiles are ordered - // by zoom level when we obtain them from getTiles(). - for (auto it = sortedTilesForInsertion.rbegin(); - it != sortedTilesForInsertion.rend(); ++it) { - if (tile.tile.id.isChildOf(it->get().tile.id)) { - skip = true; - break; - } - } - if (skip) { - continue; - } - } - auto bucket = tile.tile.getBucket(*layer->baseImpl); if (bucket) { sortedTilesForInsertion.emplace_back(tile); @@ -388,6 +371,45 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { frameHistory.record(parameters.timePoint, parameters.state.getZoom(), parameters.mapMode == MapMode::Continuous ? util::DEFAULT_TRANSITION_DURATION : Milliseconds(0)); + bool symbolBucketsChanged = false; + if (parameters.mapMode == MapMode::Still) { + // TODO: Think about right way for symbol index to handle still rendering + crossTileSymbolIndex->reset(); + } + for (auto it = order.rbegin(); it != order.rend(); ++it) { + if (it->layer.is<RenderSymbolLayer>()) { + if (crossTileSymbolIndex->addLayer(*it->layer.as<RenderSymbolLayer>())) symbolBucketsChanged = true; + } + } + + bool placementChanged = false; + if (!placement->stillRecent(parameters.timePoint)) { + auto newPlacement = std::make_unique<Placement>(parameters.state, parameters.mapMode); + for (auto it = order.rbegin(); it != order.rend(); ++it) { + if (it->layer.is<RenderSymbolLayer>()) { + newPlacement->placeLayer(*it->layer.as<RenderSymbolLayer>(), parameters.projMatrix, parameters.debugOptions & MapDebugOptions::Collision); + } + } + + placementChanged = newPlacement->commit(*placement, parameters.timePoint); + if (placementChanged || symbolBucketsChanged) { + placement = std::move(newPlacement); + } + + placement->setRecent(parameters.timePoint); + } else { + placement->setStale(); + } + + parameters.symbolFadeChange = placement->symbolFadeChange(parameters.timePoint); + + if (placementChanged || symbolBucketsChanged) { + for (auto it = order.rbegin(); it != order.rend(); ++it) { + if (it->layer.is<RenderSymbolLayer>()) { + placement->updateLayerOpacities(*it->layer.as<RenderSymbolLayer>()); + } + } + } // - UPLOAD PASS ------------------------------------------------------------------------------- // Uploads all required buffers and images before we do any actual rendering. @@ -607,7 +629,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { observer->onDidFinishRenderingFrame( loaded ? RendererObserver::RenderMode::Full : RendererObserver::RenderMode::Partial, - updateParameters.mode == MapMode::Continuous && (hasTransitions() || frameHistory.needsAnimation(util::DEFAULT_TRANSITION_DURATION)) + updateParameters.mode == MapMode::Continuous && (hasTransitions(parameters.timePoint)) ); if (!loaded) { @@ -647,7 +669,7 @@ std::vector<Feature> Renderer::Impl::queryRenderedFeatures(const ScreenLineStrin std::unordered_map<std::string, std::vector<Feature>> resultsByLayer; for (const auto& sourceID : sourceIDs) { if (RenderSource* renderSource = getRenderSource(sourceID)) { - auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, layers, options); + auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, layers, options, placement->getCollisionIndex()); std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin())); } } @@ -727,7 +749,7 @@ RenderSource* Renderer::Impl::getRenderSource(const std::string& id) const { return it != renderSources.end() ? it->second.get() : nullptr; } -bool Renderer::Impl::hasTransitions() const { +bool Renderer::Impl::hasTransitions(TimePoint timePoint) const { if (renderLight.hasTransition()) { return true; } @@ -738,6 +760,10 @@ bool Renderer::Impl::hasTransitions() const { } } + if (placement->hasTransitions(timePoint)) { + return true; + } + return false; } |