Preload tiles for WebGL tile layers

This commit is contained in:
Tim Schaub
2022-02-09 14:01:14 -07:00
parent 96de98bfbb
commit 6f005e1f30
2 changed files with 144 additions and 63 deletions
+18 -15
View File
@@ -307,10 +307,10 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
/** /**
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state. * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
* @param {import("../../extent.js").Extent} extent The extent to be rendered. * @param {import("../../extent.js").Extent} extent The extent to be rendered.
* @param {number} z The zoom level. * @param {number} initialZ The zoom level.
* @param {Object<number, Array<TileTexture>>} tileTexturesByZ The zoom level. * @param {Object<number, Array<TileTexture>>} tileTexturesByZ The zoom level.
*/ */
enqueueTiles(frameState, extent, z, tileTexturesByZ) { enqueueTiles(frameState, extent, initialZ, tileTexturesByZ) {
const viewState = frameState.viewState; const viewState = frameState.viewState;
const tileLayer = this.getLayer(); const tileLayer = this.getLayer();
const tileSource = tileLayer.getRenderSource(); const tileSource = tileLayer.getRenderSource();
@@ -318,13 +318,6 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
const tilePixelRatio = tileSource.getTilePixelRatio(frameState.pixelRatio); const tilePixelRatio = tileSource.getTilePixelRatio(frameState.pixelRatio);
const gutter = tileSource.getGutterForProjection(viewState.projection); const gutter = tileSource.getGutterForProjection(viewState.projection);
const tileTextureCache = this.tileTextureCache_;
const tileRange = tileGrid.getTileRangeForExtentAndZ(
extent,
z,
this.tempTileRange_
);
const tileSourceKey = getUid(tileSource); const tileSourceKey = getUid(tileSource);
if (!(tileSourceKey in frameState.wantedTiles)) { if (!(tileSourceKey in frameState.wantedTiles)) {
frameState.wantedTiles[tileSourceKey] = {}; frameState.wantedTiles[tileSourceKey] = {};
@@ -332,6 +325,19 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
const wantedTiles = frameState.wantedTiles[tileSourceKey]; const wantedTiles = frameState.wantedTiles[tileSourceKey];
const tileTextureCache = this.tileTextureCache_;
const minZ = Math.max(
initialZ - tileLayer.getPreload(),
tileGrid.getMinZoom(),
tileLayer.getMinZoom()
);
for (let z = initialZ; z >= minZ; --z) {
const tileRange = tileGrid.getTileRangeForExtentAndZ(
extent,
z,
this.tempTileRange_
);
const tileResolution = tileGrid.getResolution(z); const tileResolution = tileGrid.getResolution(z);
for (let x = tileRange.minX; x <= tileRange.maxX; ++x) { for (let x = tileRange.minX; x <= tileRange.maxX; ++x) {
@@ -339,14 +345,10 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
const tileCoord = createTileCoord(z, x, y, this.tempTileCoord_); const tileCoord = createTileCoord(z, x, y, this.tempTileCoord_);
const cacheKey = getCacheKey(tileSource, tileCoord); const cacheKey = getCacheKey(tileSource, tileCoord);
/** /** @type {TileTexture} */
* @type {TileTexture}
*/
let tileTexture; let tileTexture;
/** /** @type {import("../../webgl/TileTexture").TileType} */
* @type {import("../../webgl/TileTexture").TileType}
*/
let tile; let tile;
if (tileTextureCache.containsKey(cacheKey)) { if (tileTextureCache.containsKey(cacheKey)) {
@@ -401,6 +403,7 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
} }
} }
} }
}
/** /**
* Render the layer. * Render the layer.
@@ -6,6 +6,7 @@ import {VOID} from '../../../../../../src/ol/functions.js';
import {create} from '../../../../../../src/ol/transform.js'; import {create} from '../../../../../../src/ol/transform.js';
import {createCanvasContext2D} from '../../../../../../src/ol/dom.js'; import {createCanvasContext2D} from '../../../../../../src/ol/dom.js';
import {get} from '../../../../../../src/ol/proj.js'; import {get} from '../../../../../../src/ol/proj.js';
import {getUid} from '../../../../../../src/ol/util.js';
describe('ol/renderer/webgl/TileLayer', function () { describe('ol/renderer/webgl/TileLayer', function () {
/** @type {import("../../../../../../src/ol/renderer/webgl/TileLayer.js").default} */ /** @type {import("../../../../../../src/ol/renderer/webgl/TileLayer.js").default} */
@@ -105,4 +106,81 @@ describe('ol/renderer/webgl/TileLayer', function () {
tileLayer.setUseInterimTilesOnError(true); tileLayer.setUseInterimTilesOnError(true);
expect(renderer.isDrawableTile_(errorTile)).to.be(false); expect(renderer.isDrawableTile_(errorTile)).to.be(false);
}); });
describe('enqueueTiles()', () => {
it('enqueues tiles at a single zoom level (preload: 0)', () => {
renderer.prepareFrame(frameState);
const extent = [-1, -1, 1, 1];
renderer.enqueueTiles(frameState, extent, 10, {});
const source = tileLayer.getSource();
const sourceKey = getUid(source);
expect(frameState.wantedTiles[sourceKey]).to.be.an(Object);
const wantedTiles = frameState.wantedTiles[sourceKey];
const expected = {
'/10,511,511': true,
'/10,511,512': true,
'/10,512,511': true,
'/10,512,512': true,
};
expect(wantedTiles).to.eql(expected);
});
it('enqueues tiles at multiple zoom levels (preload: 2)', () => {
tileLayer.setPreload(2);
renderer.prepareFrame(frameState);
const extent = [-1, -1, 1, 1];
renderer.enqueueTiles(frameState, extent, 10, {});
const source = tileLayer.getSource();
const sourceKey = getUid(source);
expect(frameState.wantedTiles[sourceKey]).to.be.an(Object);
const wantedTiles = frameState.wantedTiles[sourceKey];
const expected = {
'/10,511,511': true,
'/10,511,512': true,
'/10,512,511': true,
'/10,512,512': true,
'/9,255,255': true,
'/9,255,256': true,
'/9,256,255': true,
'/9,256,256': true,
'/8,127,127': true,
'/8,127,128': true,
'/8,128,127': true,
'/8,128,128': true,
};
expect(wantedTiles).to.eql(expected);
});
it('does not go below layer min zoom', () => {
tileLayer.setPreload(Infinity);
tileLayer.setMinZoom(9);
renderer.prepareFrame(frameState);
const extent = [-1, -1, 1, 1];
renderer.enqueueTiles(frameState, extent, 10, {});
const source = tileLayer.getSource();
const sourceKey = getUid(source);
expect(frameState.wantedTiles[sourceKey]).to.be.an(Object);
const wantedTiles = frameState.wantedTiles[sourceKey];
const expected = {
'/10,511,511': true,
'/10,511,512': true,
'/10,512,511': true,
'/10,512,512': true,
'/9,255,255': true,
'/9,255,256': true,
'/9,256,255': true,
'/9,256,256': true,
};
expect(wantedTiles).to.eql(expected);
});
});
}); });