diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2016-09-16 18:12:23 +0200 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2016-09-20 14:10:38 +0200 |
commit | 1e8f9c75ca3f11ee5d31b033744d99b616d6b946 (patch) | |
tree | 217420faaff56dd4a1da5ee56d8d29776da3c99e | |
parent | 34e783ed9cb52686ec61c67aa37054b3083ef66c (diff) | |
download | qtlocation-mapboxgl-1e8f9c75ca3f11ee5d31b033744d99b616d6b946.tar.gz |
[core] do not render layers that are outside their zoom range
So far, we didn't properly disable layers that are outside the zoom range. This means that we rendered layers that should not have been rendered, albeit we didn't make any attempt to load tiles for those layers. However, when zooming in/out, existing tiles might already have been loaded in the source which continued to be rendered. In most cases they weren't actually visible because either the matrices weren't updated, or the clip IDs weren't set so that they would be "rendered" off-screen and clipped completely. In any case, we did way too much work.
-rw-r--r-- | src/mbgl/style/style.cpp | 23 | ||||
-rw-r--r-- | test/fixtures/map/disabled_layers/first/expected.png | bin | 0 -> 103 bytes | |||
-rw-r--r-- | test/fixtures/map/disabled_layers/second/expected.png | bin | 0 -> 103 bytes | |||
-rw-r--r-- | test/fixtures/map/disabled_layers/tile.png | bin | 0 -> 103 bytes | |||
-rw-r--r-- | test/map/map.cpp | 61 |
5 files changed, 80 insertions, 4 deletions
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 4cb267a261..a82cdec572 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -265,10 +265,18 @@ void Style::recalculate(float z, const TimePoint& timePoint, MapMode mode) { hasPendingTransitions = false; for (const auto& layer : layers) { - hasPendingTransitions |= layer->baseImpl->recalculate(parameters); + const bool hasTransitions = layer->baseImpl->recalculate(parameters); - Source* source = getSource(layer->baseImpl->source); - if (source && layer->baseImpl->needsRendering(z)) { + // Disable this layer if it doesn't need to be rendered. + const bool needsRendering = layer->baseImpl->needsRendering(zoomHistory.lastZoom); + if (!needsRendering) { + continue; + } + + hasPendingTransitions |= hasTransitions; + + // If this layer has a source, make sure that it gets loaded. + if (Source* source = getSource(layer->baseImpl->source)) { source->baseImpl->enabled = true; if (!source->baseImpl->loaded) { source->baseImpl->loadDescription(fileSource); @@ -317,8 +325,9 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions) const { } for (const auto& layer : layers) { - if (layer->baseImpl->visibility == VisibilityType::None) + if (!layer->baseImpl->needsRendering(zoomHistory.lastZoom)) { continue; + } if (const BackgroundLayer* background = layer->as<BackgroundLayer>()) { if (debugOptions & MapDebugOptions::Overdraw) { @@ -398,6 +407,9 @@ std::vector<Feature> Style::queryRenderedFeatures(const QueryParameters& paramet // Combine all results based on the style layer order. for (const auto& layer : layers) { + if (!layer->baseImpl->needsRendering(zoomHistory.lastZoom)) { + continue; + } auto it = resultsByLayer.find(layer->baseImpl->id); if (it != resultsByLayer.end()) { std::move(it->second.begin(), it->second.end(), std::back_inserter(result)); @@ -410,6 +422,9 @@ std::vector<Feature> Style::queryRenderedFeatures(const QueryParameters& paramet float Style::getQueryRadius() const { float additionalRadius = 0; for (auto& layer : layers) { + if (!layer->baseImpl->needsRendering(zoomHistory.lastZoom)) { + continue; + } additionalRadius = util::max(additionalRadius, layer->baseImpl->getQueryRadius()); } return additionalRadius; diff --git a/test/fixtures/map/disabled_layers/first/expected.png b/test/fixtures/map/disabled_layers/first/expected.png Binary files differnew file mode 100644 index 0000000000..388180c6d1 --- /dev/null +++ b/test/fixtures/map/disabled_layers/first/expected.png diff --git a/test/fixtures/map/disabled_layers/second/expected.png b/test/fixtures/map/disabled_layers/second/expected.png Binary files differnew file mode 100644 index 0000000000..089ac0dde9 --- /dev/null +++ b/test/fixtures/map/disabled_layers/second/expected.png diff --git a/test/fixtures/map/disabled_layers/tile.png b/test/fixtures/map/disabled_layers/tile.png Binary files differnew file mode 100644 index 0000000000..089ac0dde9 --- /dev/null +++ b/test/fixtures/map/disabled_layers/tile.png diff --git a/test/map/map.cpp b/test/map/map.cpp index 6ecbc52e5f..0437296350 100644 --- a/test/map/map.cpp +++ b/test/map/map.cpp @@ -249,6 +249,67 @@ TEST(Map, RemoveLayer) { test::checkImage("test/fixtures/map/remove_layer", test::render(map)); } +TEST(Map, DisabledSources) { + MapTest test; + + // Always load the same image tile for raster layers. + test.fileSource.response = [] (const Resource& res) -> optional<Response> { + if (res.url == "asset://tile.png") { + Response response; + response.data = std::make_shared<std::string>( + util::read_file("test/fixtures/map/disabled_layers/tile.png")); + return {std::move(response)}; + } + return {}; + }; + + Map map(test.view, test.fileSource, MapMode::Still); + map.setZoom(1); + + // This stylesheet has two raster layers, one that starts at zoom 1, the other at zoom 0. + // We first render a map at zoom level 1, which should show both layers (both are "visible" due + // to an opacity of 0.5). Then, we are zooming back out to a zoom level of 0.5 and rerender. + // The "raster1" layer should not be visible anymore since it has minzoom 1, while "raster2" + // should still be there. Both layers have a distinct color through "raster-hue-rotate". + map.setStyleJSON(R"STYLE( +{ + "version": 8, + "name": "Test", + "sources": { + "raster": { + "type": "raster", + "tiles": [ "asset://tile.png" ], + "tileSize": 256 + } + }, + "layers": [{ + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, { + "id": "raster1", + "type": "raster", + "source": "raster", + "minzoom": 0 + }, { + "id": "raster2", + "type": "raster", + "source": "raster", + "minzoom": 1, + "paint": { + "raster-hue-rotate": 180 + } + }] +} +)STYLE"); + + test::checkImage("test/fixtures/map/disabled_layers/first", test::render(map)); + map.setZoom(0.5); + test::checkImage("test/fixtures/map/disabled_layers/second", test::render(map)); +} + TEST(Map, Classes) { MapTest test; |