Merge pull request #14051 from mike-000/fix-preload-and-empty-reproj
Fix WebGL preload and empty reproj tiles
This commit is contained in:
@@ -181,7 +181,10 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
pixelRatio,
|
pixelRatio,
|
||||||
projection
|
projection
|
||||||
);
|
);
|
||||||
if (!(tile instanceof ImageTile || tile instanceof ReprojTile)) {
|
if (
|
||||||
|
!(tile instanceof ImageTile || tile instanceof ReprojTile) ||
|
||||||
|
(tile instanceof ReprojTile && tile.getState() === TileState.EMPTY)
|
||||||
|
) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* @module ol/renderer/webgl/TileLayer
|
* @module ol/renderer/webgl/TileLayer
|
||||||
*/
|
*/
|
||||||
import LRUCache from '../../structs/LRUCache.js';
|
import LRUCache from '../../structs/LRUCache.js';
|
||||||
|
import ReprojTile from '../../reproj/Tile.js';
|
||||||
import TileRange from '../../TileRange.js';
|
import TileRange from '../../TileRange.js';
|
||||||
import TileState from '../../TileState.js';
|
import TileState from '../../TileState.js';
|
||||||
import TileTexture from '../../webgl/TileTexture.js';
|
import TileTexture from '../../webgl/TileTexture.js';
|
||||||
@@ -316,8 +317,9 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
|||||||
* @param {import("../../extent.js").Extent} extent The extent to be rendered.
|
* @param {import("../../extent.js").Extent} extent The extent to be rendered.
|
||||||
* @param {number} initialZ 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.
|
||||||
|
* @param {number} preload Number of additional levels to load.
|
||||||
*/
|
*/
|
||||||
enqueueTiles(frameState, extent, initialZ, tileTexturesByZ) {
|
enqueueTiles(frameState, extent, initialZ, tileTexturesByZ, preload) {
|
||||||
const viewState = frameState.viewState;
|
const viewState = frameState.viewState;
|
||||||
const tileLayer = this.getLayer();
|
const tileLayer = this.getLayer();
|
||||||
const tileSource = tileLayer.getRenderSource();
|
const tileSource = tileLayer.getRenderSource();
|
||||||
@@ -330,12 +332,23 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const wantedTiles = frameState.wantedTiles[tileSourceKey];
|
const wantedTiles = frameState.wantedTiles[tileSourceKey];
|
||||||
|
|
||||||
const tileTextureCache = this.tileTextureCache_;
|
const tileTextureCache = this.tileTextureCache_;
|
||||||
|
|
||||||
|
const map = tileLayer.getMapInternal();
|
||||||
const minZ = Math.max(
|
const minZ = Math.max(
|
||||||
initialZ - tileLayer.getPreload(),
|
initialZ - preload,
|
||||||
tileGrid.getMinZoom(),
|
tileGrid.getMinZoom(),
|
||||||
tileLayer.getMinZoom()
|
tileGrid.getZForResolution(
|
||||||
|
Math.min(
|
||||||
|
tileLayer.getMaxResolution(),
|
||||||
|
map
|
||||||
|
? map
|
||||||
|
.getView()
|
||||||
|
.getResolutionForZoom(Math.max(tileLayer.getMinZoom(), 0))
|
||||||
|
: tileGrid.getResolution(0)
|
||||||
|
),
|
||||||
|
tileSource.zDirection
|
||||||
|
)
|
||||||
);
|
);
|
||||||
for (let z = initialZ; z >= minZ; --z) {
|
for (let z = initialZ; z >= minZ; --z) {
|
||||||
const tileRange = tileGrid.getTileRangeForExtentAndZ(
|
const tileRange = tileGrid.getTileRangeForExtentAndZ(
|
||||||
@@ -437,16 +450,34 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
|||||||
*/
|
*/
|
||||||
const tileTexturesByZ = {};
|
const tileTexturesByZ = {};
|
||||||
|
|
||||||
|
const preload = tileLayer.getPreload();
|
||||||
if (frameState.nextExtent) {
|
if (frameState.nextExtent) {
|
||||||
const targetZ = tileGrid.getZForResolution(
|
const targetZ = tileGrid.getZForResolution(
|
||||||
viewState.nextResolution,
|
viewState.nextResolution,
|
||||||
tileSource.zDirection
|
tileSource.zDirection
|
||||||
);
|
);
|
||||||
const nextExtent = getRenderExtent(frameState, frameState.nextExtent);
|
const nextExtent = getRenderExtent(frameState, frameState.nextExtent);
|
||||||
this.enqueueTiles(frameState, nextExtent, targetZ, tileTexturesByZ);
|
this.enqueueTiles(
|
||||||
|
frameState,
|
||||||
|
nextExtent,
|
||||||
|
targetZ,
|
||||||
|
tileTexturesByZ,
|
||||||
|
preload
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.enqueueTiles(frameState, extent, z, tileTexturesByZ);
|
this.enqueueTiles(frameState, extent, z, tileTexturesByZ, 0);
|
||||||
|
if (preload > 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.enqueueTiles(
|
||||||
|
frameState,
|
||||||
|
extent,
|
||||||
|
z - 1,
|
||||||
|
tileTexturesByZ,
|
||||||
|
preload - 1
|
||||||
|
);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A lookup of alpha values for tiles at the target rendering resolution
|
* A lookup of alpha values for tiles at the target rendering resolution
|
||||||
@@ -465,6 +496,9 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
|||||||
for (let i = 0, ii = tileTextures.length; i < ii; ++i) {
|
for (let i = 0, ii = tileTextures.length; i < ii; ++i) {
|
||||||
const tileTexture = tileTextures[i];
|
const tileTexture = tileTextures[i];
|
||||||
const tile = tileTexture.tile;
|
const tile = tileTexture.tile;
|
||||||
|
if (tile instanceof ReprojTile && tile.getState() === TileState.EMPTY) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const tileCoord = tile.tileCoord;
|
const tileCoord = tile.tileCoord;
|
||||||
|
|
||||||
if (tileTexture.loaded) {
|
if (tileTexture.loaded) {
|
||||||
@@ -753,6 +787,10 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const tileTexture = tileTextureCache.get(cacheKey);
|
const tileTexture = tileTextureCache.get(cacheKey);
|
||||||
|
const tile = tileTexture.tile;
|
||||||
|
if (tile instanceof ReprojTile && tile.getState() === TileState.EMPTY) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (!tileTexture.loaded) {
|
if (!tileTexture.loaded) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
import Map from '../../../../../../src/ol/Map.js';
|
||||||
import TileQueue from '../../../../../../src/ol/TileQueue.js';
|
import TileQueue from '../../../../../../src/ol/TileQueue.js';
|
||||||
import TileState from '../../../../../../src/ol/TileState.js';
|
import TileState from '../../../../../../src/ol/TileState.js';
|
||||||
|
import View from '../../../../../../src/ol/View.js';
|
||||||
import WebGLTileLayer from '../../../../../../src/ol/layer/WebGLTile.js';
|
import WebGLTileLayer from '../../../../../../src/ol/layer/WebGLTile.js';
|
||||||
import {DataTile} from '../../../../../../src/ol/source.js';
|
import {DataTile} from '../../../../../../src/ol/source.js';
|
||||||
import {VOID} from '../../../../../../src/ol/functions.js';
|
import {VOID} from '../../../../../../src/ol/functions.js';
|
||||||
@@ -15,6 +17,8 @@ describe('ol/renderer/webgl/TileLayer', function () {
|
|||||||
let tileLayer;
|
let tileLayer;
|
||||||
/** @type {import('../../../../../../src/ol/Map.js').FrameState} */
|
/** @type {import('../../../../../../src/ol/Map.js').FrameState} */
|
||||||
let frameState;
|
let frameState;
|
||||||
|
/** @type {Map} */
|
||||||
|
let map;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
const size = 256;
|
const size = 256;
|
||||||
const context = createCanvasContext2D(size, size);
|
const context = createCanvasContext2D(size, size);
|
||||||
@@ -54,10 +58,16 @@ describe('ol/renderer/webgl/TileLayer', function () {
|
|||||||
tileQueue: new TileQueue(VOID, VOID),
|
tileQueue: new TileQueue(VOID, VOID),
|
||||||
renderTargets: {},
|
renderTargets: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
map = new Map({
|
||||||
|
view: new View(),
|
||||||
|
});
|
||||||
|
tileLayer.set('map', map, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
tileLayer.dispose();
|
tileLayer.dispose();
|
||||||
|
map.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('maintains a cache on the renderer instead of the source', function () {
|
it('maintains a cache on the renderer instead of the source', function () {
|
||||||
@@ -111,7 +121,7 @@ describe('ol/renderer/webgl/TileLayer', function () {
|
|||||||
it('enqueues tiles at a single zoom level (preload: 0)', () => {
|
it('enqueues tiles at a single zoom level (preload: 0)', () => {
|
||||||
renderer.prepareFrame(frameState);
|
renderer.prepareFrame(frameState);
|
||||||
const extent = [-1, -1, 1, 1];
|
const extent = [-1, -1, 1, 1];
|
||||||
renderer.enqueueTiles(frameState, extent, 10, {});
|
renderer.enqueueTiles(frameState, extent, 10, {}, tileLayer.getPreload());
|
||||||
|
|
||||||
const source = tileLayer.getSource();
|
const source = tileLayer.getSource();
|
||||||
const sourceKey = getUid(source);
|
const sourceKey = getUid(source);
|
||||||
@@ -132,7 +142,7 @@ describe('ol/renderer/webgl/TileLayer', function () {
|
|||||||
tileLayer.setPreload(2);
|
tileLayer.setPreload(2);
|
||||||
renderer.prepareFrame(frameState);
|
renderer.prepareFrame(frameState);
|
||||||
const extent = [-1, -1, 1, 1];
|
const extent = [-1, -1, 1, 1];
|
||||||
renderer.enqueueTiles(frameState, extent, 10, {});
|
renderer.enqueueTiles(frameState, extent, 10, {}, tileLayer.getPreload());
|
||||||
|
|
||||||
const source = tileLayer.getSource();
|
const source = tileLayer.getSource();
|
||||||
const sourceKey = getUid(source);
|
const sourceKey = getUid(source);
|
||||||
@@ -162,7 +172,7 @@ describe('ol/renderer/webgl/TileLayer', function () {
|
|||||||
tileLayer.setMinZoom(9);
|
tileLayer.setMinZoom(9);
|
||||||
renderer.prepareFrame(frameState);
|
renderer.prepareFrame(frameState);
|
||||||
const extent = [-1, -1, 1, 1];
|
const extent = [-1, -1, 1, 1];
|
||||||
renderer.enqueueTiles(frameState, extent, 10, {});
|
renderer.enqueueTiles(frameState, extent, 10, {}, tileLayer.getPreload());
|
||||||
|
|
||||||
const source = tileLayer.getSource();
|
const source = tileLayer.getSource();
|
||||||
const sourceKey = getUid(source);
|
const sourceKey = getUid(source);
|
||||||
@@ -182,5 +192,38 @@ describe('ol/renderer/webgl/TileLayer', function () {
|
|||||||
};
|
};
|
||||||
expect(wantedTiles).to.eql(expected);
|
expect(wantedTiles).to.eql(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('layer min zoom relates to view zoom levels', () => {
|
||||||
|
map.setView(
|
||||||
|
new View({maxResolution: map.getView().getMaxResolution() * 2})
|
||||||
|
);
|
||||||
|
tileLayer.setPreload(Infinity);
|
||||||
|
tileLayer.setMinZoom(9);
|
||||||
|
renderer.prepareFrame(frameState);
|
||||||
|
const extent = [-1, -1, 1, 1];
|
||||||
|
renderer.enqueueTiles(frameState, extent, 10, {}, tileLayer.getPreload());
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
BIN
test/rendering/cases/webgl-tile-preload/expected.png
Normal file
BIN
test/rendering/cases/webgl-tile-preload/expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
20
test/rendering/cases/webgl-tile-preload/main.js
Normal file
20
test/rendering/cases/webgl-tile-preload/main.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import Map from '../../../../src/ol/Map.js';
|
||||||
|
import TileDebug from '../../../../src/ol/source/TileDebug.js';
|
||||||
|
import TileLayer from '../../../../src/ol/layer/WebGLTile.js';
|
||||||
|
import View from '../../../../src/ol/View.js';
|
||||||
|
|
||||||
|
new Map({
|
||||||
|
target: 'map',
|
||||||
|
layers: [
|
||||||
|
new TileLayer({
|
||||||
|
source: new TileDebug(),
|
||||||
|
preload: Infinity,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
view: new View({
|
||||||
|
center: [0, 0],
|
||||||
|
zoom: 0.5,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
render();
|
||||||
Reference in New Issue
Block a user