diff --git a/src/source/source_cache.js b/src/source/source_cache.js index d2d097b130b..127f01143b1 100644 --- a/src/source/source_cache.js +++ b/src/source/source_cache.js @@ -368,16 +368,14 @@ class SourceCache extends Evented { */ findLoadedParent(tileID: OverscaledTileID, minCoveringZoom: number): ?Tile { for (let z = tileID.overscaledZ - 1; z >= minCoveringZoom; z--) { - const parent = tileID.scaledTo(z); - if (!parent) return; - const id = String(parent.key); - const tile = this._tiles[id]; + const parentKey = tileID.calculateScaledKey(z, 1); + const tile = this._tiles[parentKey]; if (tile && tile.hasData()) { return tile; } - if (this._cache.has(parent)) { - return this._cache.get(parent); - } + const parentWrappedKey = tileID.calculateScaledKey(z, 0); + const cachedTile = this._cache.getByKey(parentWrappedKey); + if (cachedTile) return cachedTile; } } diff --git a/src/source/tile_cache.js b/src/source/tile_cache.js index a78c002eb7c..1bf01cc0948 100644 --- a/src/source/tile_cache.js +++ b/src/source/tile_cache.js @@ -122,6 +122,14 @@ class TileCache { return data.value; } + /* + * Get the value with the specified (wrapped tile) key. + */ + getByKey(key: number): ?Tile { + const data = this.data[key]; + return data ? data[0].value : null; + } + /** * Get the value attached to a specific key without removing data * from the cache. If the key is not found, returns `null` diff --git a/src/source/tile_id.js b/src/source/tile_id.js index 9d39d3eae7b..fa87284eeaa 100644 --- a/src/source/tile_id.js +++ b/src/source/tile_id.js @@ -95,6 +95,20 @@ export class OverscaledTileID { } } + /* + * calculateScaledKey with withWrap values 1 or 0, is an optimization: it implements + * this.scaledTo(z).key or this.scaledTo(z).wrapped().key, respectively. + */ + calculateScaledKey(targetZ: number, withWrap: 0 | 1) { + assert(targetZ <= this.overscaledZ); + const zDifference = this.canonical.z - targetZ; + if (targetZ > this.canonical.z) { + return calculateKey(this.wrap * withWrap, targetZ, this.canonical.x, this.canonical.y); + } else { + return calculateKey(this.wrap * withWrap, targetZ, this.canonical.x >> zDifference, this.canonical.y >> zDifference); + } + } + isChildOf(parent: OverscaledTileID) { if (parent.wrap !== this.wrap) { // We can't be a child if we're in a different world copy