diff --git a/circle.yml b/circle.yml index 66ebaf0226a..081ab9a3bdf 100644 --- a/circle.yml +++ b/circle.yml @@ -619,8 +619,8 @@ commands: - run: name: Run tests command: | - # Source.RenderTileSetSourceUpdate is filtered out due to #15294 - xvfb-run --server-args="-screen 0 1024x768x24" make run-test--Source.RenderTileSetSourceUpdate 2> >(tee sanitizer 1>&2) + # Source.RenderTileSetSourceUpdate and Source.InvisibleSourcesTileNecessity are filtered out due to #15294 + xvfb-run --server-args="-screen 0 1024x768x24" make run-test--Source.RenderTileSetSourceUpdate:Source.InvisibleSourcesTileNecessity 2> >(tee sanitizer 1>&2) # Unfortunately, Google Test eats the status code, so we'll have to check the output. [ -z "$(sed -n '/^SUMMARY: .*Sanitizer:/p' sanitizer)" ] diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index e42082fd2ff..14a68537c22 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -4,6 +4,9 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to ## master +### Bug fixes + - Suppress network requests for expired tiles update, if these tiles are invisible. [#15741](https://github.com/mapbox/mapbox-gl-native/pull/15741) + ## 8.4.0 - September 25, 2019 [Changes](https://github.com/mapbox/mapbox-gl-native/compare/android-v8.4.0-beta.1...android-v8.4.0) since [Mapbox Maps SDK for Android v8.4.0-beta.1](https://github.com/mapbox/mapbox-gl-native/releases/tag/android-v8.4.0-beta.1): diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index a326161595f..b7caf0485ab 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -2,6 +2,12 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started. +## master + +### Other changes + +* Suppress network requests for expired tiles update, if these tiles are invisible. ([#15741](https://github.com/mapbox/mapbox-gl-native/pull/15741)) + ## 5.4.0 - September 25, 2019 ### Styles and rendering diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp index 2bf6e2e1a9c..586d3b5a8ae 100644 --- a/src/mbgl/renderer/tile_pyramid.cpp +++ b/src/mbgl/renderer/tile_pyramid.cpp @@ -68,6 +68,10 @@ void TilePyramid::update(const std::vector>& l if (!needsRendering) { if (!needsRelayout) { for (auto& entry : tiles) { + // These tiles are invisible, we set optional necessity + // for them and thus suppress network requests on + // tiles expiration (see `OnlineFileRequest`). + entry.second->setNecessity(TileNecessity::Optional); cache.add(entry.first, std::move(entry.second)); } } diff --git a/test/style/source.test.cpp b/test/style/source.test.cpp index ca0e79f46ad..a08d11c7ad8 100644 --- a/test/style/source.test.cpp +++ b/test/style/source.test.cpp @@ -35,10 +35,11 @@ #include #include -#include #include #include +#include #include +#include #include #include @@ -793,6 +794,79 @@ TEST(Source, CustomGeometrySourceSetTileData) { test.run(); } +namespace { + +class FakeTileSource; + +class FakeTile : public Tile { +public: + FakeTile(FakeTileSource& source_, const OverscaledTileID& tileID) + : Tile(Tile::Kind::Geometry, tileID), source(source_) { + renderable = true; + } + void setNecessity(TileNecessity necessity) override; + bool layerPropertiesUpdated(const Immutable&) override { return true; } + + std::unique_ptr createRenderData() override { return nullptr; } + +private: + FakeTileSource& source; +}; + +class FakeTileSource : public RenderTileSetSource { +public: + MOCK_METHOD1(tileSetNecessity, void(TileNecessity)); + + explicit FakeTileSource(Immutable impl_) : RenderTileSetSource(std::move(impl_)) {} + void updateInternal(const Tileset& tileset, + const std::vector>& layers, + const bool needsRendering, + const bool needsRelayout, + const TileParameters& parameters) override { + tilePyramid.update(layers, + needsRendering, + needsRelayout, + parameters, + SourceType::Vector, + util::tileSize, + tileset.zoomRange, + tileset.bounds, + [&](const OverscaledTileID& tileID) { return std::make_unique(*this, tileID); }); + } + + const optional& getTileset() const override { + return static_cast(*baseImpl).tileset; + } +}; + +void FakeTile::setNecessity(TileNecessity necessity) { + source.tileSetNecessity(necessity); +} + +} // namespace + +TEST(Source, InvisibleSourcesTileNecessity) { + SourceTest test; + VectorSource initialized("source", Tileset{{"tiles"}}); + initialized.loadDescription(*test.fileSource); + + FakeTileSource renderTilesetSource{initialized.baseImpl}; + RenderSource* renderSource = &renderTilesetSource; + LineLayer layer("id", "source"); + Immutable layerProperties = + makeMutable(staticImmutableCast(layer.baseImpl)); + std::vector> layers{layerProperties}; + EXPECT_CALL(renderTilesetSource, tileSetNecessity(TileNecessity::Required)).Times(1); + renderSource->update(initialized.baseImpl, layers, true, true, test.tileParameters); + + // Necessity for invisible tiles must be set to `optional`. + EXPECT_CALL(renderTilesetSource, tileSetNecessity(TileNecessity::Optional)).Times(1); + renderSource->update(initialized.baseImpl, layers, false, false, test.tileParameters); + + // Necessity is again `required` once tiles get back visible. + EXPECT_CALL(renderTilesetSource, tileSetNecessity(TileNecessity::Required)).Times(1); + renderSource->update(initialized.baseImpl, layers, true, false, test.tileParameters); +} TEST(Source, RenderTileSetSourceUpdate) { SourceTest test;