Preload tiles for WebGL tile layers
This commit is contained in:
@@ -307,10 +307,10 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
||||
/**
|
||||
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
|
||||
* @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.
|
||||
*/
|
||||
enqueueTiles(frameState, extent, z, tileTexturesByZ) {
|
||||
enqueueTiles(frameState, extent, initialZ, tileTexturesByZ) {
|
||||
const viewState = frameState.viewState;
|
||||
const tileLayer = this.getLayer();
|
||||
const tileSource = tileLayer.getRenderSource();
|
||||
@@ -318,13 +318,6 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
||||
const tilePixelRatio = tileSource.getTilePixelRatio(frameState.pixelRatio);
|
||||
const gutter = tileSource.getGutterForProjection(viewState.projection);
|
||||
|
||||
const tileTextureCache = this.tileTextureCache_;
|
||||
const tileRange = tileGrid.getTileRangeForExtentAndZ(
|
||||
extent,
|
||||
z,
|
||||
this.tempTileRange_
|
||||
);
|
||||
|
||||
const tileSourceKey = getUid(tileSource);
|
||||
if (!(tileSourceKey in frameState.wantedTiles)) {
|
||||
frameState.wantedTiles[tileSourceKey] = {};
|
||||
@@ -332,70 +325,80 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
||||
|
||||
const wantedTiles = frameState.wantedTiles[tileSourceKey];
|
||||
|
||||
const tileResolution = tileGrid.getResolution(z);
|
||||
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_
|
||||
);
|
||||
|
||||
for (let x = tileRange.minX; x <= tileRange.maxX; ++x) {
|
||||
for (let y = tileRange.minY; y <= tileRange.maxY; ++y) {
|
||||
const tileCoord = createTileCoord(z, x, y, this.tempTileCoord_);
|
||||
const cacheKey = getCacheKey(tileSource, tileCoord);
|
||||
const tileResolution = tileGrid.getResolution(z);
|
||||
|
||||
/**
|
||||
* @type {TileTexture}
|
||||
*/
|
||||
let tileTexture;
|
||||
for (let x = tileRange.minX; x <= tileRange.maxX; ++x) {
|
||||
for (let y = tileRange.minY; y <= tileRange.maxY; ++y) {
|
||||
const tileCoord = createTileCoord(z, x, y, this.tempTileCoord_);
|
||||
const cacheKey = getCacheKey(tileSource, tileCoord);
|
||||
|
||||
/**
|
||||
* @type {import("../../webgl/TileTexture").TileType}
|
||||
*/
|
||||
let tile;
|
||||
/** @type {TileTexture} */
|
||||
let tileTexture;
|
||||
|
||||
if (tileTextureCache.containsKey(cacheKey)) {
|
||||
tileTexture = tileTextureCache.get(cacheKey);
|
||||
tile = tileTexture.tile;
|
||||
}
|
||||
if (!tileTexture || tileTexture.tile.key !== tileSource.getKey()) {
|
||||
tile = tileSource.getTile(
|
||||
z,
|
||||
x,
|
||||
y,
|
||||
frameState.pixelRatio,
|
||||
viewState.projection
|
||||
);
|
||||
if (!tileTexture) {
|
||||
tileTexture = new TileTexture({
|
||||
tile: tile,
|
||||
grid: tileGrid,
|
||||
helper: this.helper,
|
||||
tilePixelRatio: tilePixelRatio,
|
||||
gutter: gutter,
|
||||
});
|
||||
tileTextureCache.set(cacheKey, tileTexture);
|
||||
} else {
|
||||
if (this.isDrawableTile_(tile)) {
|
||||
tileTexture.setTile(tile);
|
||||
/** @type {import("../../webgl/TileTexture").TileType} */
|
||||
let tile;
|
||||
|
||||
if (tileTextureCache.containsKey(cacheKey)) {
|
||||
tileTexture = tileTextureCache.get(cacheKey);
|
||||
tile = tileTexture.tile;
|
||||
}
|
||||
if (!tileTexture || tileTexture.tile.key !== tileSource.getKey()) {
|
||||
tile = tileSource.getTile(
|
||||
z,
|
||||
x,
|
||||
y,
|
||||
frameState.pixelRatio,
|
||||
viewState.projection
|
||||
);
|
||||
if (!tileTexture) {
|
||||
tileTexture = new TileTexture({
|
||||
tile: tile,
|
||||
grid: tileGrid,
|
||||
helper: this.helper,
|
||||
tilePixelRatio: tilePixelRatio,
|
||||
gutter: gutter,
|
||||
});
|
||||
tileTextureCache.set(cacheKey, tileTexture);
|
||||
} else {
|
||||
const interimTile =
|
||||
/** @type {import("../../webgl/TileTexture").TileType} */ (
|
||||
tile.getInterimTile()
|
||||
);
|
||||
tileTexture.setTile(interimTile);
|
||||
if (this.isDrawableTile_(tile)) {
|
||||
tileTexture.setTile(tile);
|
||||
} else {
|
||||
const interimTile =
|
||||
/** @type {import("../../webgl/TileTexture").TileType} */ (
|
||||
tile.getInterimTile()
|
||||
);
|
||||
tileTexture.setTile(interimTile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addTileTextureToLookup(tileTexturesByZ, tileTexture, z);
|
||||
addTileTextureToLookup(tileTexturesByZ, tileTexture, z);
|
||||
|
||||
const tileQueueKey = tile.getKey();
|
||||
wantedTiles[tileQueueKey] = true;
|
||||
const tileQueueKey = tile.getKey();
|
||||
wantedTiles[tileQueueKey] = true;
|
||||
|
||||
if (tile.getState() === TileState.IDLE) {
|
||||
if (!frameState.tileQueue.isKeyQueued(tileQueueKey)) {
|
||||
frameState.tileQueue.enqueue([
|
||||
tile,
|
||||
tileSourceKey,
|
||||
tileGrid.getTileCoordCenter(tileCoord),
|
||||
tileResolution,
|
||||
]);
|
||||
if (tile.getState() === TileState.IDLE) {
|
||||
if (!frameState.tileQueue.isKeyQueued(tileQueueKey)) {
|
||||
frameState.tileQueue.enqueue([
|
||||
tile,
|
||||
tileSourceKey,
|
||||
tileGrid.getTileCoordCenter(tileCoord),
|
||||
tileResolution,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {VOID} from '../../../../../../src/ol/functions.js';
|
||||
import {create} from '../../../../../../src/ol/transform.js';
|
||||
import {createCanvasContext2D} from '../../../../../../src/ol/dom.js';
|
||||
import {get} from '../../../../../../src/ol/proj.js';
|
||||
import {getUid} from '../../../../../../src/ol/util.js';
|
||||
|
||||
describe('ol/renderer/webgl/TileLayer', function () {
|
||||
/** @type {import("../../../../../../src/ol/renderer/webgl/TileLayer.js").default} */
|
||||
@@ -105,4 +106,81 @@ describe('ol/renderer/webgl/TileLayer', function () {
|
||||
tileLayer.setUseInterimTilesOnError(true);
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user