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,
projection
);
if (!(tile instanceof ImageTile || tile instanceof ReprojTile)) {
if (
!(tile instanceof ImageTile || tile instanceof ReprojTile) ||
(tile instanceof ReprojTile && tile.getState() === TileState.EMPTY)
) {
return null;
}

View File

@@ -2,6 +2,7 @@
* @module ol/renderer/webgl/TileLayer
*/
import LRUCache from '../../structs/LRUCache.js';
import ReprojTile from '../../reproj/Tile.js';
import TileRange from '../../TileRange.js';
import TileState from '../../TileState.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 {number} initialZ 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 tileLayer = this.getLayer();
const tileSource = tileLayer.getRenderSource();
@@ -330,12 +332,23 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
}
const wantedTiles = frameState.wantedTiles[tileSourceKey];
const tileTextureCache = this.tileTextureCache_;
const map = tileLayer.getMapInternal();
const minZ = Math.max(
initialZ - tileLayer.getPreload(),
initialZ - preload,
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) {
const tileRange = tileGrid.getTileRangeForExtentAndZ(
@@ -437,16 +450,34 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
*/
const tileTexturesByZ = {};
const preload = tileLayer.getPreload();
if (frameState.nextExtent) {
const targetZ = tileGrid.getZForResolution(
viewState.nextResolution,
tileSource.zDirection
);
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
@@ -465,6 +496,9 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
for (let i = 0, ii = tileTextures.length; i < ii; ++i) {
const tileTexture = tileTextures[i];
const tile = tileTexture.tile;
if (tile instanceof ReprojTile && tile.getState() === TileState.EMPTY) {
continue;
}
const tileCoord = tile.tileCoord;
if (tileTexture.loaded) {
@@ -753,6 +787,10 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
continue;
}
const tileTexture = tileTextureCache.get(cacheKey);
const tile = tileTexture.tile;
if (tile instanceof ReprojTile && tile.getState() === TileState.EMPTY) {
return null;
}
if (!tileTexture.loaded) {
continue;
}

View File

@@ -1,5 +1,7 @@
import Map from '../../../../../../src/ol/Map.js';
import TileQueue from '../../../../../../src/ol/TileQueue.js';
import TileState from '../../../../../../src/ol/TileState.js';
import View from '../../../../../../src/ol/View.js';
import WebGLTileLayer from '../../../../../../src/ol/layer/WebGLTile.js';
import {DataTile} from '../../../../../../src/ol/source.js';
import {VOID} from '../../../../../../src/ol/functions.js';
@@ -15,6 +17,8 @@ describe('ol/renderer/webgl/TileLayer', function () {
let tileLayer;
/** @type {import('../../../../../../src/ol/Map.js').FrameState} */
let frameState;
/** @type {Map} */
let map;
beforeEach(function () {
const size = 256;
const context = createCanvasContext2D(size, size);
@@ -54,10 +58,16 @@ describe('ol/renderer/webgl/TileLayer', function () {
tileQueue: new TileQueue(VOID, VOID),
renderTargets: {},
};
map = new Map({
view: new View(),
});
tileLayer.set('map', map, true);
});
afterEach(function () {
tileLayer.dispose();
map.dispose();
});
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)', () => {
renderer.prepareFrame(frameState);
const extent = [-1, -1, 1, 1];
renderer.enqueueTiles(frameState, extent, 10, {});
renderer.enqueueTiles(frameState, extent, 10, {}, tileLayer.getPreload());
const source = tileLayer.getSource();
const sourceKey = getUid(source);
@@ -132,7 +142,7 @@ describe('ol/renderer/webgl/TileLayer', function () {
tileLayer.setPreload(2);
renderer.prepareFrame(frameState);
const extent = [-1, -1, 1, 1];
renderer.enqueueTiles(frameState, extent, 10, {});
renderer.enqueueTiles(frameState, extent, 10, {}, tileLayer.getPreload());
const source = tileLayer.getSource();
const sourceKey = getUid(source);
@@ -162,7 +172,7 @@ describe('ol/renderer/webgl/TileLayer', function () {
tileLayer.setMinZoom(9);
renderer.prepareFrame(frameState);
const extent = [-1, -1, 1, 1];
renderer.enqueueTiles(frameState, extent, 10, {});
renderer.enqueueTiles(frameState, extent, 10, {}, tileLayer.getPreload());
const source = tileLayer.getSource();
const sourceKey = getUid(source);
@@ -182,5 +192,38 @@ describe('ol/renderer/webgl/TileLayer', function () {
};
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();