diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp index 2bf6e2e1a..586d3b5a8 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 ca0e79f46..a08d11c7a 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;