diff options
m--------- | mapbox-gl-js | 0 | ||||
-rw-r--r-- | platform/node/test/suite_implementation.js | 2 | ||||
-rw-r--r-- | src/mbgl/algorithm/update_renderables.hpp | 15 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile.cpp | 25 | ||||
-rw-r--r-- | src/mbgl/tile/raster_tile.cpp | 8 | ||||
-rw-r--r-- | src/mbgl/tile/tile.hpp | 34 | ||||
-rw-r--r-- | test/algorithm/mock.hpp | 5 | ||||
-rw-r--r-- | test/algorithm/update_renderables.test.cpp | 33 | ||||
-rw-r--r-- | test/tile/raster_tile.test.cpp | 8 | ||||
-rw-r--r-- | test/tile/vector_tile.test.cpp | 6 |
10 files changed, 100 insertions, 36 deletions
diff --git a/mapbox-gl-js b/mapbox-gl-js -Subproject cfb4525fc9cdb5e4f9ec49f8d503cea88017d5a +Subproject fbea8565244ad254eb9678798b4a21c88916dd8 diff --git a/platform/node/test/suite_implementation.js b/platform/node/test/suite_implementation.js index ef97652893..a5e96f7265 100644 --- a/platform/node/test/suite_implementation.js +++ b/platform/node/test/suite_implementation.js @@ -17,6 +17,8 @@ module.exports = function (style, options, callback) { request(req.url, {encoding: null}, function (err, response, body) { if (err) { callback(err); + } else if (response.statusCode == 404) { + callback(); } else if (response.statusCode != 200) { callback(new Error(response.statusMessage)); } else { diff --git a/src/mbgl/algorithm/update_renderables.hpp b/src/mbgl/algorithm/update_renderables.hpp index fe2dc2c570..a9c348b538 100644 --- a/src/mbgl/algorithm/update_renderables.hpp +++ b/src/mbgl/algorithm/update_renderables.hpp @@ -43,7 +43,9 @@ void updateRenderables(GetTileFn getTile, retainTile(*tile, Resource::Necessity::Required); renderTile(idealRenderTileID, *tile); } else { - bool triedPrevious = tile->hasTriedOptional(); + // We are now attempting to load child and parent tiles. + bool parentHasTriedOptional = tile->hasTriedOptional(); + bool parentIsLoaded = tile->isLoaded(); // The tile isn't loaded yet, but retain it anyway because it's an ideal tile. retainTile(*tile, Resource::Necessity::Required); @@ -91,13 +93,18 @@ void updateRenderables(GetTileFn getTile, } tile = getTile(parentDataTileID); - if (!tile && triedPrevious) { + if (!tile && (parentHasTriedOptional || parentIsLoaded)) { tile = createTile(parentDataTileID); } if (tile) { - triedPrevious = tile->hasTriedOptional(); - retainTile(*tile, Resource::Necessity::Optional); + retainTile(*tile, parentIsLoaded ? Resource::Necessity::Required + : Resource::Necessity::Optional); + + // Save the current values, since they're the parent of the next iteration + // of the parent tile ascent loop. + parentHasTriedOptional = tile->hasTriedOptional(); + parentIsLoaded = tile->isLoaded(); if (tile->isRenderable()) { renderTile(parentRenderTileID, *tile); diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index c9ed46a529..d3406e1a59 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -52,15 +52,15 @@ void GeometryTile::cancel() { } void GeometryTile::setError(std::exception_ptr err) { + loaded = true; + renderable = false; observer->onTileError(*this, err); } void GeometryTile::setData(std::unique_ptr<const GeometryTileData> data_) { // Mark the tile as pending again if it was complete before to prevent signaling a complete // state despite pending parse operations. - if (availableData == DataAvailability::All) { - availableData = DataAvailability::Some; - } + pending = true; ++correlationID; worker.invoke(&GeometryTileWorker::setData, std::move(data_), correlationID); @@ -74,9 +74,7 @@ void GeometryTile::setPlacementConfig(const PlacementConfig& desiredConfig) { // Mark the tile as pending again if it was complete before to prevent signaling a complete // state despite pending parse operations. - if (availableData == DataAvailability::All) { - availableData = DataAvailability::Some; - } + pending = true; ++correlationID; requestedConfig = desiredConfig; @@ -86,9 +84,7 @@ void GeometryTile::setPlacementConfig(const PlacementConfig& desiredConfig) { void GeometryTile::redoLayout() { // Mark the tile as pending again if it was complete before to prevent signaling a complete // state despite pending parse operations. - if (availableData == DataAvailability::All) { - availableData = DataAvailability::Some; - } + pending = true; std::vector<std::unique_ptr<Layer>> copy; @@ -111,7 +107,8 @@ void GeometryTile::redoLayout() { } void GeometryTile::onLayout(LayoutResult result) { - availableData = DataAvailability::Some; + loaded = true; + renderable = true; nonSymbolBuckets = std::move(result.nonSymbolBuckets); featureIndex = std::move(result.featureIndex); data = std::move(result.tileData); @@ -120,8 +117,10 @@ void GeometryTile::onLayout(LayoutResult result) { } void GeometryTile::onPlacement(PlacementResult result) { + loaded = true; + renderable = true; if (result.correlationID == correlationID) { - availableData = DataAvailability::All; + pending = false; } symbolBuckets = std::move(result.symbolBuckets); collisionTile = std::move(result.collisionTile); @@ -129,7 +128,9 @@ void GeometryTile::onPlacement(PlacementResult result) { } void GeometryTile::onError(std::exception_ptr err) { - availableData = DataAvailability::All; + loaded = true; + pending = false; + renderable = false; observer->onTileError(*this, err); } diff --git a/src/mbgl/tile/raster_tile.cpp b/src/mbgl/tile/raster_tile.cpp index 887ebb67b8..1e3c772200 100644 --- a/src/mbgl/tile/raster_tile.cpp +++ b/src/mbgl/tile/raster_tile.cpp @@ -28,6 +28,8 @@ void RasterTile::cancel() { } void RasterTile::setError(std::exception_ptr err) { + loaded = true; + renderable = false; observer->onTileError(*this, err); } @@ -41,13 +43,15 @@ void RasterTile::setData(std::shared_ptr<const std::string> data, void RasterTile::onParsed(std::unique_ptr<Bucket> result) { bucket = std::move(result); - availableData = bucket ? DataAvailability::All : DataAvailability::None; + loaded = true; + renderable = bucket ? true : false; observer->onTileChanged(*this); } void RasterTile::onError(std::exception_ptr err) { bucket.reset(); - availableData = DataAvailability::None; + loaded = true; + renderable = false; observer->onTileError(*this, err); } diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp index a8034c40e4..b3085071c2 100644 --- a/src/mbgl/tile/tile.hpp +++ b/src/mbgl/tile/tile.hpp @@ -74,11 +74,23 @@ public: // partial state is still waiting for network resources but can also // be rendered, although layers will be missing. bool isRenderable() const { - return availableData != DataAvailability::None; + return renderable; } + // A tile is "Loaded" when we have received a response from a FileSource, and have attempted to + // parse the tile (if applicable). Tile implementations should set this to true when a load + // error occurred, or after the tile was parsed successfully. + bool isLoaded() const { + return loaded; + } + + // "Completion" of a tile means that we have attempted to load it, and parsed it completely, + // i.e. no parsing or placement operations are pending for that tile. + // Completeness doesn't mean that the tile can be rendered, but merely that we have exhausted + // all options to get this tile to a renderable state. Some tiles may not be renderable, but + // complete, e.g. when a raster tile couldn't be loaded, or parsing failed. bool isComplete() const { - return availableData == DataAvailability::All; + return loaded && !pending; } void dumpDebugLogs() const; @@ -92,21 +104,9 @@ public: protected: bool triedOptional = false; - - enum class DataAvailability : uint8_t { - // Still waiting for data to load or parse. - None, - - // Tile is partially parsed, some buckets are still waiting for dependencies - // to arrive, but it is good for rendering. Partial tiles can also be re-parsed, - // but might remain in the same state if dependencies are still missing. - Some, - - // Tile is fully parsed, and all buckets are available if they exist. - All, - }; - - DataAvailability availableData = DataAvailability::None; + bool renderable = false; + bool pending = false; + bool loaded = false; TileObserver* observer = nullptr; }; diff --git a/test/algorithm/mock.hpp b/test/algorithm/mock.hpp index efa76f238e..d87f55343b 100644 --- a/test/algorithm/mock.hpp +++ b/test/algorithm/mock.hpp @@ -34,8 +34,13 @@ struct MockTileData { return renderable; } + bool isLoaded() const { + return loaded; + } + bool renderable = false; bool triedOptional = false; + bool loaded = false; const mbgl::OverscaledTileID tileID; }; diff --git a/test/algorithm/update_renderables.test.cpp b/test/algorithm/update_renderables.test.cpp index c284c37475..af90d262de 100644 --- a/test/algorithm/update_renderables.test.cpp +++ b/test/algorithm/update_renderables.test.cpp @@ -1226,3 +1226,36 @@ TEST(UpdateRenderables, RepeatedRenderWithMissingOptionals) { }), log); } + +TEST(UpdateRenderables, LoadRequiredIfIdealTileCantBeFound) { + ActionLog log; + MockSource source; + auto getTileData = getTileDataFn(log, source.dataTiles); + auto createTileData = createTileDataFn(log, source.dataTiles); + auto retainTileData = retainTileDataFn(log); + auto renderTile = renderTileFn(log); + + source.zoomRange.max = 6; + source.idealTiles.emplace(UnwrappedTileID{ 6, 0, 0 }); + + auto tile_6_6_0_0 = source.createTileData(OverscaledTileID{ 6, { 6, 0, 0 } }); + tile_6_6_0_0->triedOptional = true; + tile_6_6_0_0->loaded = true; + + algorithm::updateRenderables(getTileData, createTileData, retainTileData, renderTile, + source.idealTiles, source.zoomRange, 6); + EXPECT_EQ(ActionLog({ + GetTileDataAction{ { 6, { 6, 0, 0 } }, Found }, // ideal tile, not found + RetainTileDataAction{ { 6, { 6, 0, 0 } }, Resource::Necessity::Required }, // + GetTileDataAction{ { 7, { 6, 0, 0 } }, NotFound }, // overzoomed child + GetTileDataAction{ { 5, { 5, 0, 0 } }, NotFound }, // ascent + CreateTileDataAction{ { 5, { 5, 0, 0 } } }, + RetainTileDataAction{ { 5, { 5, 0, 0 } }, Resource::Necessity::Required }, + GetTileDataAction{ { 4, { 4, 0, 0 } }, NotFound }, // ... + GetTileDataAction{ { 3, { 3, 0, 0 } }, NotFound }, // ... + GetTileDataAction{ { 2, { 2, 0, 0 } }, NotFound }, // ... + GetTileDataAction{ { 1, { 1, 0, 0 } }, NotFound }, // ... + GetTileDataAction{ { 0, { 0, 0, 0 } }, NotFound }, // ... + }), + log); +} diff --git a/test/tile/raster_tile.test.cpp b/test/tile/raster_tile.test.cpp index 5cfc274be0..d0252555ac 100644 --- a/test/tile/raster_tile.test.cpp +++ b/test/tile/raster_tile.test.cpp @@ -40,6 +40,8 @@ TEST(RasterTile, setError) { RasterTile tile(OverscaledTileID(0, 0, 0), test.updateParameters, test.tileset); tile.setError(std::make_exception_ptr(std::runtime_error("test"))); EXPECT_FALSE(tile.isRenderable()); + EXPECT_TRUE(tile.isLoaded()); + EXPECT_TRUE(tile.isComplete()); } TEST(RasterTile, onError) { @@ -47,6 +49,8 @@ TEST(RasterTile, onError) { RasterTile tile(OverscaledTileID(0, 0, 0), test.updateParameters, test.tileset); tile.onError(std::make_exception_ptr(std::runtime_error("test"))); EXPECT_FALSE(tile.isRenderable()); + EXPECT_TRUE(tile.isLoaded()); + EXPECT_TRUE(tile.isComplete()); } TEST(RasterTile, onParsed) { @@ -54,6 +58,8 @@ TEST(RasterTile, onParsed) { RasterTile tile(OverscaledTileID(0, 0, 0), test.updateParameters, test.tileset); tile.onParsed(std::make_unique<RasterBucket>(UnassociatedImage{})); EXPECT_TRUE(tile.isRenderable()); + EXPECT_TRUE(tile.isLoaded()); + EXPECT_TRUE(tile.isComplete()); } TEST(RasterTile, onParsedEmpty) { @@ -61,4 +67,6 @@ TEST(RasterTile, onParsedEmpty) { RasterTile tile(OverscaledTileID(0, 0, 0), test.updateParameters, test.tileset); tile.onParsed(nullptr); EXPECT_FALSE(tile.isRenderable()); + EXPECT_TRUE(tile.isLoaded()); + EXPECT_TRUE(tile.isComplete()); } diff --git a/test/tile/vector_tile.test.cpp b/test/tile/vector_tile.test.cpp index a388e8937e..0f43645d49 100644 --- a/test/tile/vector_tile.test.cpp +++ b/test/tile/vector_tile.test.cpp @@ -46,13 +46,17 @@ TEST(VectorTile, setError) { VectorTile tile(OverscaledTileID(0, 0, 0), "source", test.updateParameters, test.tileset); tile.setError(std::make_exception_ptr(std::runtime_error("test"))); EXPECT_FALSE(tile.isRenderable()); + EXPECT_TRUE(tile.isLoaded()); + EXPECT_TRUE(tile.isComplete()); } TEST(VectorTile, onError) { VectorTileTest test; VectorTile tile(OverscaledTileID(0, 0, 0), "source", test.updateParameters, test.tileset); tile.onError(std::make_exception_ptr(std::runtime_error("test"))); - EXPECT_TRUE(tile.isRenderable()); + EXPECT_FALSE(tile.isRenderable()); + EXPECT_TRUE(tile.isLoaded()); + EXPECT_TRUE(tile.isComplete()); } TEST(VectorTile, Issue7615) { |