summaryrefslogtreecommitdiff
path: root/src/mbgl/algorithm/update_renderables.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/algorithm/update_renderables.hpp')
-rw-r--r--src/mbgl/algorithm/update_renderables.hpp219
1 files changed, 134 insertions, 85 deletions
diff --git a/src/mbgl/algorithm/update_renderables.hpp b/src/mbgl/algorithm/update_renderables.hpp
index c583b6b2b6..cf1ad8af65 100644
--- a/src/mbgl/algorithm/update_renderables.hpp
+++ b/src/mbgl/algorithm/update_renderables.hpp
@@ -1,127 +1,176 @@
#pragma once
+#include <mbgl/tile/tile.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/tile/tile_necessity.hpp>
#include <mbgl/util/range.hpp>
#include <unordered_set>
+#include <iostream>
+
namespace mbgl {
namespace algorithm {
+
template <typename GetTileFn,
typename CreateTileFn,
typename RetainTileFn,
- typename RenderTileFn,
- typename IdealTileIDs>
-void updateRenderables(GetTileFn getTile,
+ typename RenderTileFn>
+bool findBestTile(GetTileFn getTile,
CreateTileFn createTile,
RetainTileFn retainTile,
RenderTileFn renderTile,
- const IdealTileIDs& idealTileIDs,
const Range<uint8_t>& zoomRange,
- const uint8_t dataTileZoom) {
- std::unordered_set<UnwrappedTileID> checked;
- bool covered;
- int32_t overscaledZ;
+ const uint8_t dataTileZoom,
+ const UnwrappedTileID& idealRenderTileID,
+ const OverscaledTileID& idealDataTileID,
+ const bool requireFullyRenderable,
+ std::unordered_set<UnwrappedTileID> checked) {
- // for (all in the set of ideal tiles of the source) {
- for (const auto& idealRenderTileID : idealTileIDs) {
- assert(idealRenderTileID.canonical.z >= zoomRange.min);
- assert(idealRenderTileID.canonical.z <= zoomRange.max);
- assert(dataTileZoom >= idealRenderTileID.canonical.z);
+ auto tile = getTile(idealDataTileID);
+ if (!tile) {
+ std::cout << "Create tile: " << idealDataTileID << std::endl;
+ tile = createTile(idealDataTileID);
+ assert(tile);
+ }
- const OverscaledTileID idealDataTileID(dataTileZoom, idealRenderTileID.wrap, idealRenderTileID.canonical);
- auto tile = getTile(idealDataTileID);
- if (!tile) {
- tile = createTile(idealDataTileID);
- assert(tile);
- }
+ bool covered = true;
+ std::vector<std::pair<UnwrappedTileID,Tile*>> renderTiles;
+ // if (source has the tile and bucket is loaded) {
+ if (requireFullyRenderable ? tile->isFullyRenderable() : tile->isRenderable()) {
+ retainTile(*tile, TileNecessity::Required);
+ renderTiles.emplace_back(std::make_pair(idealRenderTileID, tile));
+ } else {
+ // We are now attempting to load child and parent tiles.
+ bool parentHasTriedOptional = tile->hasTriedCache();
+ bool parentIsLoaded = tile->isLoaded();
+
+ // The tile isn't loaded yet, but retain it anyway because it's an ideal tile.
+ retainTile(*tile, TileNecessity::Required); // TODO: Is it fine to retain this twice for both full and partial render?
- // if (source has the tile and bucket is loaded) {
- if (tile->isRenderable()) {
- retainTile(*tile, TileNecessity::Required);
- renderTile(idealRenderTileID, *tile);
+
+ int32_t overscaledZ = dataTileZoom + 1;
+ if (overscaledZ > zoomRange.max) {
+ // We're looking for an overzoomed child tile.
+ const auto childDataTileID = idealDataTileID.scaledTo(overscaledZ);
+ tile = getTile(childDataTileID);
+ if (tile && (requireFullyRenderable ? tile->isFullyRenderable() : tile->isRenderable())) {
+ retainTile(*tile, TileNecessity::Optional);
+ renderTiles.emplace_back(std::make_pair(idealRenderTileID, tile));
+ } else {
+ covered = false;
+ }
} else {
- // We are now attempting to load child and parent tiles.
- bool parentHasTriedOptional = tile->hasTriedCache();
- bool parentIsLoaded = tile->isLoaded();
-
- // The tile isn't loaded yet, but retain it anyway because it's an ideal tile.
- retainTile(*tile, TileNecessity::Required);
- covered = true;
- overscaledZ = dataTileZoom + 1;
- if (overscaledZ > zoomRange.max) {
- // We're looking for an overzoomed child tile.
- const auto childDataTileID = idealDataTileID.scaledTo(overscaledZ);
+ // Check all four actual child tiles.
+ for (const auto& childTileID : idealDataTileID.canonical.children()) {
+ const OverscaledTileID childDataTileID(overscaledZ, idealRenderTileID.wrap, childTileID);
tile = getTile(childDataTileID);
- if (tile && tile->isRenderable()) {
+ if (tile && (requireFullyRenderable ? tile->isFullyRenderable() : tile->isRenderable())) {
retainTile(*tile, TileNecessity::Optional);
- renderTile(idealRenderTileID, *tile);
+ renderTiles.emplace_back(std::make_pair(childDataTileID.toUnwrapped(), tile));
} else {
+ // At least one child tile doesn't exist, so we are going to look for
+ // parents as well.
covered = false;
}
- } else {
- // Check all four actual child tiles.
- for (const auto& childTileID : idealDataTileID.canonical.children()) {
- const OverscaledTileID childDataTileID(overscaledZ, idealRenderTileID.wrap, childTileID);
- tile = getTile(childDataTileID);
- if (tile && tile->isRenderable()) {
- retainTile(*tile, TileNecessity::Optional);
- renderTile(childDataTileID.toUnwrapped(), *tile);
- } else {
- // At least one child tile doesn't exist, so we are going to look for
- // parents as well.
- covered = false;
- }
- }
}
+ }
- if (!covered) {
- // We couldn't find child tiles that entirely cover the ideal tile.
- for (overscaledZ = dataTileZoom - 1; overscaledZ >= zoomRange.min; --overscaledZ) {
- const auto parentDataTileID = idealDataTileID.scaledTo(overscaledZ);
- const auto parentRenderTileID = parentDataTileID.toUnwrapped();
+ if (!covered) {
+ // We couldn't find child tiles that entirely cover the ideal tile.
+ for (overscaledZ = dataTileZoom - 1; overscaledZ >= zoomRange.min; --overscaledZ) {
+ const auto parentDataTileID = idealDataTileID.scaledTo(overscaledZ);
+ const auto parentRenderTileID = parentDataTileID.toUnwrapped();
- if (checked.find(parentRenderTileID) != checked.end()) {
- // Break parent tile ascent, this route has been checked by another child
- // tile before.
- break;
+ if (checked.find(parentRenderTileID) != checked.end()) {
+ // Break parent tile ascent, this route has been checked by another child
+ // tile before.
+ break;
+ } else {
+ checked.emplace(parentRenderTileID);
+ }
+
+ tile = getTile(parentDataTileID);
+ // Don't do cache lookups for parents while we're in the "fully renderable" pass:
+ // Since the cache tiles aren't currently displaying, we don't have to worry about symbol flicker
+ // And we'd rather get a partially rendered tile closer to our ideal zoom level
+ if (!tile && !requireFullyRenderable && (parentHasTriedOptional || parentIsLoaded)) {
+ tile = createTile(parentDataTileID);
+ }
+
+ if (tile) {
+ if (!parentIsLoaded) {
+ // We haven't completed loading the child, so we only do an optional
+ // (cache) request in an attempt to quickly load data that we can show.
+ retainTile(*tile, TileNecessity::Optional);
} else {
- checked.emplace(parentRenderTileID);
+ // Now that we've checked the child and know for sure that we can't load
+ // it, we attempt to load the parent from the network.
+ retainTile(*tile, TileNecessity::Required);
}
- tile = getTile(parentDataTileID);
- if (!tile && (parentHasTriedOptional || parentIsLoaded)) {
- tile = createTile(parentDataTileID);
- }
+ // Save the current values, since they're the parent of the next iteration
+ // of the parent tile ascent loop.
+ parentHasTriedOptional = tile->hasTriedCache();
+ parentIsLoaded = tile->isLoaded();
- if (tile) {
- if (!parentIsLoaded) {
- // We haven't completed loading the child, so we only do an optional
- // (cache) request in an attempt to quickly load data that we can show.
- retainTile(*tile, TileNecessity::Optional);
- } else {
- // Now that we've checked the child and know for sure that we can't load
- // it, we attempt to load the parent from the network.
- retainTile(*tile, TileNecessity::Required);
- }
-
- // Save the current values, since they're the parent of the next iteration
- // of the parent tile ascent loop.
- parentHasTriedOptional = tile->hasTriedCache();
- parentIsLoaded = tile->isLoaded();
-
- if (tile->isRenderable()) {
- renderTile(parentRenderTileID, *tile);
- // Break parent tile ascent, since we found one.
- break;
- }
+ if ((requireFullyRenderable ? tile->isFullyRenderable() : tile->isRenderable())) {
+ std::cout << "Rendering parent zoom change: " << parentRenderTileID.canonical.z - idealRenderTileID.canonical.z << std::endl;
+ renderTiles.emplace_back(std::make_pair(parentRenderTileID, tile));
+ covered = true;
+ // Break parent tile ascent, since we found one.
+ break;
}
}
}
}
}
+ if (covered || !requireFullyRenderable) {
+ // Only add tiles to render tree if we've covered the ideal tile OR we're on our second pass
+ for (auto tilePair : renderTiles) {
+ // std::cout << "Rendering tile: " << tilePair.first << std::endl;
+ renderTile(tilePair.first, *(tilePair.second));
+ }
+ } else {
+ std::cout << "No tiles added to render tree" << std::endl;
+ }
+ return covered;
+}
+
+template <typename GetTileFn,
+ typename CreateTileFn,
+ typename RetainTileFn,
+ typename RenderTileFn,
+ typename IdealTileIDs>
+void updateRenderables(GetTileFn getTile,
+ CreateTileFn createTile,
+ RetainTileFn retainTile,
+ RenderTileFn renderTile,
+ const IdealTileIDs& idealTileIDs,
+ const Range<uint8_t>& zoomRange,
+ const uint8_t dataTileZoom) {
+ std::unordered_set<UnwrappedTileID> checkedPartial;
+ std::unordered_set<UnwrappedTileID> checkedFull;
+
+ std::cout << "Begin updateRenderables" << std::endl;
+
+ // for (all in the set of ideal tiles of the source) {
+ for (const auto& idealRenderTileID : idealTileIDs) {
+ assert(idealRenderTileID.canonical.z >= zoomRange.min);
+ assert(idealRenderTileID.canonical.z <= zoomRange.max);
+ assert(dataTileZoom >= idealRenderTileID.canonical.z);
+
+ const OverscaledTileID idealDataTileID(dataTileZoom, idealRenderTileID.wrap, idealRenderTileID.canonical);
+
+ std::cout << "Ideal tile ID: " << idealDataTileID << std::endl;
+
+ // TODO: Two-pass algorithm isn't necessary for tiles that don't have two stage loading (e.g. raster tiles)
+ // TODO: More efficient to write algorithm as single pass?
+ if (!findBestTile(getTile, createTile, retainTile, renderTile, zoomRange, dataTileZoom, idealRenderTileID, idealDataTileID, true, checkedFull)) {
+ findBestTile(getTile, createTile, retainTile, renderTile, zoomRange, dataTileZoom, idealRenderTileID, idealDataTileID, false, checkedPartial);
+ }
+ }
}
} // namespace algorithm