diff --git a/src/ol/renderer/webgl/TileLayer.js b/src/ol/renderer/webgl/TileLayer.js index 951bef91d2..e6e97a3646 100644 --- a/src/ol/renderer/webgl/TileLayer.js +++ b/src/ol/renderer/webgl/TileLayer.js @@ -160,6 +160,22 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer { this.renderedOpacity_ = NaN; } + /** + * @protected + * @param {import("../../Tile.js").default} tile Tile. + * @return {boolean} Tile is drawable. + */ + isDrawableTile(tile) { + const tileLayer = this.getLayer(); + const tileState = tile.getState(); + const useInterimTilesOnError = tileLayer.getUseInterimTilesOnError(); + return ( + tileState == TileState.LOADED || + tileState == TileState.EMPTY || + (tileState == TileState.ERROR && !useInterimTilesOnError) + ); + } + /** * Determine whether render should be called. * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. @@ -222,30 +238,38 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer { const tileCoord = createTileCoord(z, x, y, this.tempTileCoord_); const tileCoordKey = getTileCoordKey(tileCoord); - let tileTexture; + let tileTexture, tile; if (tileTextureCache.containsKey(tileCoordKey)) { tileTexture = tileTextureCache.get(tileCoordKey); - } else { - const tile = tileSource.getTile( + tile = tileTexture.tile; + } + if (!tileTexture || tileTexture.tile.key !== tileSource.getKey()) { + tile = tileSource.getTile( z, x, y, frameState.pixelRatio, viewState.projection ); - tileTexture = new TileTexture(tile, tileGrid, this.helper); - tileTextureCache.set(tileCoordKey, tileTexture); + if (!tileTexture) { + tileTexture = new TileTexture(tile, tileGrid, this.helper); + tileTextureCache.set(tileCoordKey, tileTexture); + } else { + tileTexture.setTile( + this.isDrawableTile(tile) ? tile : tile.getInterimTile() + ); + } } addTileTextureToLookup(tileTexturesByZ, tileTexture, z); - const tileQueueKey = tileTexture.tile.getKey(); + const tileQueueKey = tile.getKey(); wantedTiles[tileQueueKey] = true; - if (tileTexture.tile.getState() === TileState.IDLE) { + if (tile.getState() === TileState.IDLE) { if (!frameState.tileQueue.isKeyQueued(tileQueueKey)) { frameState.tileQueue.enqueue([ - tileTexture.tile, + tile, tileSourceKey, tileGrid.getTileCoordCenter(tileCoord), tileResolution, diff --git a/src/ol/webgl/TileTexture.js b/src/ol/webgl/TileTexture.js index cad02dc42e..5c26e8e9b6 100644 --- a/src/ol/webgl/TileTexture.js +++ b/src/ol/webgl/TileTexture.js @@ -83,14 +83,24 @@ class TileTexture extends EventTarget { constructor(tile, grid, helper) { super(); - this.tile = tile; + /** + * @type {import("../DataTile.js").default|import("../ImageTile.js").default} + */ + this.tile; + + /** + * @type {Array} + */ + this.textures = []; + this.handleTileChange_ = this.handleTileChange_.bind(this); + + this.setTile(tile); + this.size = toSize(grid.getTileSize(tile.tileCoord[0])); - this.loaded = tile.getState() === TileState.LOADED; this.bandCount = NaN; this.helper_ = helper; - this.handleTileChange_ = this.handleTileChange_.bind(this); const coords = new WebGLArrayBuffer(ARRAY_BUFFER, STATIC_DRAW); coords.fromArray([ @@ -105,16 +115,24 @@ class TileTexture extends EventTarget { ]); helper.flushBufferData(coords); this.coords = coords; + } - /** - * @type {Array} - */ - this.textures = []; - - if (this.loaded) { - this.uploadTile_(); - } else { - tile.addEventListener(EventType.CHANGE, this.handleTileChange_); + /** + * @param {import("../DataTile.js").default|import("../ImageTile.js").default} tile Tile. + */ + setTile(tile) { + if (tile !== this.tile) { + if (this.tile) { + this.tile.removeEventListener(EventType.CHANGE, this.handleTileChange_); + } + this.tile = tile; + this.textures.length = 0; + this.loaded = tile.getState() === TileState.LOADED; + if (this.loaded) { + this.uploadTile_(); + } else { + tile.addEventListener(EventType.CHANGE, this.handleTileChange_); + } } }