Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prevent overdraw by not retaining parent tiles for sparse tilesets #7051

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions src/source/source_cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class SourceCache extends Evented {
_isIdRenderable: (id: number, symbolLayer?: boolean) => boolean;
used: boolean;
_state: SourceFeatureState;
sparse: boolean;

static maxUnderzooming: number;
static maxOverzooming: number;
Expand Down Expand Up @@ -559,7 +560,6 @@ class SourceCache extends Evented {
const checked: {[number]: boolean } = {};
const minCoveringZoom = Math.max(zoom - SourceCache.maxOverzooming, this._source.minzoom);
const maxCoveringZoom = Math.max(zoom + SourceCache.maxUnderzooming, this._source.minzoom);

const missingTiles = {};
for (const tileID of idealTileIDs) {
const tile = this._addTile(tileID);
Expand Down Expand Up @@ -610,14 +610,35 @@ class SourceCache extends Evented {
// tile has been previously requested (and errored because we only loop over tiles with no data)
// in order to determine if we need to request its parent.
let parentWasRequested = tile.wasRequested();
const raster = isRasterType(this._source.type);

for (let overscaledZ = tileID.overscaledZ - 1; overscaledZ >= minCoveringZoom; --overscaledZ) {
const minZoom = this.sparse ? tileID.overscaledZ - 1 : minCoveringZoom;
for (let overscaledZ = tileID.overscaledZ - 1; overscaledZ >= minZoom; --overscaledZ) {
const parentId = tileID.scaledTo(overscaledZ);

// Break parent tile ascent if this route has been previously checked by another child.
if (checked[parentId.key]) break;
checked[parentId.key] = true;

if (!raster) {
let siblingFailed = false, siblingLoaded = false;
parentId.children(this._source.maxzoom).forEach((sibID) => {
const sibling = this.getTile(sibID);
if (sibling) {
if (sibling.hasData()) {
siblingLoaded = true;
}
if (sibling.state === 'errored') siblingFailed = true;
}
});
if (siblingLoaded && siblingFailed) {
// mark this tileset as sparse, so other tiles' only retain parents one ZL above the
// ideal zoom to prevent overdraw from other anscenstors
if (!this.sparse) this.sparse = true;
// don't retain parent for errored tiles with loaded siblings to prevent overdraw
break;
}
}

tile = this.getTile(parentId);
if (!tile && parentWasRequested) {
tile = this._addTile(parentId);
Expand Down