Merge pull request #14051 from mike-000/fix-preload-and-empty-reproj

Fix WebGL preload and empty reproj tiles
This commit is contained in:
Tim Schaub
2022-08-25 17:12:38 +02:00
committed by GitHub
5 changed files with 114 additions and 10 deletions

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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);
});
}); });
}); });

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View 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();