summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2017-04-19 18:25:50 +0200
committerKonstantin Käfer <mail@kkaefer.com>2017-04-20 09:38:18 +0200
commit9a9408e8111bcdcd0fcb9a93112d61ab8fce0601 (patch)
tree1498222077d463ad4b8a3b1fb479696de6716512
parent7ddca3b6116903bae9ecde1d49d29a8f1fedcec3 (diff)
downloadqtlocation-mapboxgl-9a9408e8111bcdcd0fcb9a93112d61ab8fce0601.tar.gz
[core] Render parent raster tiles when ideal tile can't be loaded
m---------mapbox-gl-js0
-rw-r--r--platform/node/test/suite_implementation.js2
-rw-r--r--src/mbgl/algorithm/update_renderables.hpp15
-rw-r--r--src/mbgl/tile/geometry_tile.cpp25
-rw-r--r--src/mbgl/tile/raster_tile.cpp8
-rw-r--r--src/mbgl/tile/tile.hpp34
-rw-r--r--test/algorithm/mock.hpp5
-rw-r--r--test/algorithm/update_renderables.test.cpp33
-rw-r--r--test/tile/raster_tile.test.cpp8
-rw-r--r--test/tile/vector_tile.test.cpp6
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) {