Merge pull request #13336 from MoonE/dispose-webgl

Dispose of webgl contexts
This commit is contained in:
MoonE
2022-02-07 22:38:36 +01:00
committed by GitHub
10 changed files with 114 additions and 88 deletions

View File

@@ -469,6 +469,7 @@ describe('ol/Map', function () {
document.body.removeChild(map.getTargetElement());
map.setTarget(null);
map.dispose();
map.getLayers().forEach((layer) => layer.dispose());
});
it('triggers when all tiles and sources are loaded and faded in', function (done) {

View File

@@ -6,35 +6,41 @@ import VectorSource from '../../../../../src/ol/source/Vector.js';
import View from '../../../../../src/ol/View.js';
describe('ol/layer/Heatmap', function () {
/** @type {HTMLDivElement} */
let target;
/** @type {Map} */
let map;
/** @type {HeatmapLayer} */
let layer;
beforeEach(() => {
target = document.createElement('div');
target.style.width = '300px';
target.style.height = '300px';
document.body.appendChild(target);
map = new Map({
view: new View({
center: [0, 0],
resolution: 0.1,
}),
target: target,
});
});
afterEach(() => {
map.dispose();
document.body.removeChild(target);
layer.dispose();
});
describe('constructor', function () {
let target, map;
beforeEach(() => {
target = document.createElement('div');
target.style.width = '300px';
target.style.height = '300px';
document.body.appendChild(target);
map = new Map({
view: new View({
center: [0, 0],
resolution: 0.1,
}),
target: target,
});
});
afterEach(() => {
map.dispose();
document.body.removeChild(target);
});
it('can be constructed without arguments', function () {
const instance = new HeatmapLayer();
expect(instance).to.be.an(HeatmapLayer);
layer = new HeatmapLayer();
expect(layer).to.be.an(HeatmapLayer);
});
it('has a default className', function () {
const layer = new HeatmapLayer({
layer = new HeatmapLayer({
source: new VectorSource(),
});
map.addLayer(layer);
@@ -45,7 +51,7 @@ describe('ol/layer/Heatmap', function () {
});
it('accepts a custom className', function () {
const layer = new HeatmapLayer({
layer = new HeatmapLayer({
source: new VectorSource(),
className: 'a-class-name',
});
@@ -59,11 +65,6 @@ describe('ol/layer/Heatmap', function () {
describe('hit detection', function () {
it('hit detects two distinct features', function (done) {
const target = document.createElement('div');
target.style.width = '300px';
target.style.height = '300px';
document.body.appendChild(target);
const feature = new Feature({
geometry: new Point([0, 0]),
id: 1,
@@ -78,19 +79,12 @@ describe('ol/layer/Heatmap', function () {
const source = new VectorSource({
features: [feature, feature2],
});
const layer = new HeatmapLayer({
layer = new HeatmapLayer({
source: source,
blur: 10,
radius: 10,
});
const map = new Map({
layers: [layer],
view: new View({
center: [0, 0],
resolution: 0.1,
}),
target: target,
});
map.addLayer(layer);
map.render();
function hitTest(coordinate) {
@@ -118,7 +112,6 @@ describe('ol/layer/Heatmap', function () {
res = hitTest([0, 14]);
expect(res).to.be(null);
document.body.removeChild(target);
done();
});
});

View File

@@ -50,6 +50,7 @@ describe('ol/layer/WebGLTile', function () {
afterEach(function () {
map.setTarget(null);
document.body.removeChild(target);
map.getLayers().forEach((layer) => layer.dispose());
});
describe('dispose()', () => {
@@ -63,7 +64,7 @@ describe('ol/layer/WebGLTile', function () {
it('creates fragment and vertex shaders', function () {
const compileShaderSpy = sinon.spy(WebGLHelper.prototype, 'compileShader');
const renderer = layer.createRenderer();
const renderer = layer.getRenderer();
const viewState = map.getView().getState();
const size = map.getSize();
const frameState = {
@@ -164,7 +165,7 @@ describe('ol/layer/WebGLTile', function () {
});
const compileShaderSpy = sinon.spy(WebGLHelper.prototype, 'compileShader');
const renderer = layer.createRenderer();
const renderer = layer.getRenderer();
const viewState = map.getView().getState();
const size = map.getSize();
const frameState = {
@@ -259,7 +260,7 @@ describe('ol/layer/WebGLTile', function () {
});
it('can be called before the layer is rendered', function () {
const layer = new WebGLTileLayer({
layer = new WebGLTileLayer({
style: {
variables: {
foo: 'bar',

View File

@@ -103,6 +103,7 @@ describe('ol/renderer/webgl/PointsLayer', function () {
fragmentShader: simpleFragmentShader,
});
expect(renderer).to.be.a(WebGLPointsLayerRenderer);
renderer.dispose();
});
});
@@ -127,6 +128,10 @@ describe('ol/renderer/webgl/PointsLayer', function () {
});
});
afterEach(function () {
renderer.dispose();
});
it('calls WebGlHelper#prepareDraw', function () {
renderer.prepareFrame(frameState);
@@ -320,6 +325,10 @@ describe('ol/renderer/webgl/PointsLayer', function () {
});
});
afterEach(function () {
renderer.dispose();
});
it('correctly hit detects a feature', function (done) {
const transform = composeTransform(
createTransform(),
@@ -456,7 +465,7 @@ describe('ol/renderer/webgl/PointsLayer', function () {
const spyHelper = sinon.spy(renderer.helper, 'disposeInternal');
const spyWorker = sinon.spy(renderer.worker_, 'terminate');
renderer.disposeInternal();
renderer.dispose();
expect(spyHelper.called).to.be(true);
expect(spyWorker.called).to.be(true);
});
@@ -672,6 +681,10 @@ describe('ol/renderer/webgl/PointsLayer', function () {
};
});
afterEach(function () {
renderer.dispose();
});
it('fires prerender and postrender events', function (done) {
let prerenderNotified = false;
let postrenderNotified = false;
@@ -720,6 +733,7 @@ describe('ol/renderer/webgl/PointsLayer', function () {
afterEach(function () {
disposeMap(map);
layer.dispose();
});
it('is completely rendered on rendercomplete', function (done) {
@@ -808,6 +822,7 @@ describe('ol/renderer/webgl/PointsLayer', function () {
});
afterEach(function () {
disposeMap(map);
layer.dispose();
});
it('allows changing variables', function (done) {

View File

@@ -30,7 +30,7 @@ describe('ol/renderer/webgl/TileLayer', function () {
}),
});
renderer = tileLayer.createRenderer();
renderer = tileLayer.getRenderer();
const proj = get('EPSG:3857');
frameState = {
@@ -55,6 +55,10 @@ describe('ol/renderer/webgl/TileLayer', function () {
};
});
afterEach(function () {
tileLayer.dispose();
});
it('maintains a cache on the renderer instead of the source', function () {
expect(tileLayer.getSource().tileCache.highWaterMark).to.be(0.1);
expect(renderer.tileTextureCache_.highWaterMark).to.be(512);

View File

@@ -13,39 +13,39 @@ import {getUid} from '../../../../../src/ol/util.js';
const VERTEX_SHADER = `
precision mediump float;
uniform mat4 u_offsetScaleMatrix;
uniform mat4 u_offsetRotateMatrix;
uniform float u_time;
uniform float u_zoom;
uniform float u_resolution;
attribute float a_test;
uniform float u_test;
void main(void) {
gl_Position = vec4(u_test, a_test, 0.0, 1.0);
}`;
const INVALID_VERTEX_SHADER = `
precision mediump float;
uniform mat4 u_offsetScaleMatrix;
uniform mat4 u_offsetRotateMatrix;
uniform float u_time;
uniform float u_zoom;
uniform float u_resolution;
bla
uniform float u_test;
void main(void) {
gl_Position = vec4(u_test, a_test, 0.0, 1.0);
}`;
const FRAGMENT_SHADER = `
precision mediump float;
void main(void) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}`;
@@ -58,9 +58,13 @@ const INVALID_FRAGMENT_SHADER = `
}`;
describe('ol/webgl/WebGLHelper', function () {
let h;
afterEach(function () {
h.dispose();
});
describe('constructor', function () {
describe('without an argument', function () {
let h;
beforeEach(function () {
h = new WebGLHelper();
});
@@ -76,7 +80,6 @@ describe('ol/webgl/WebGLHelper', function () {
});
describe('with post process passes', function () {
let h;
beforeEach(function () {
h = new WebGLHelper({
postProcesses: [
@@ -105,7 +108,6 @@ describe('ol/webgl/WebGLHelper', function () {
describe('operations', function () {
describe('prepare draw', function () {
let h;
beforeEach(function () {
h = new WebGLHelper({
uniforms: {
@@ -157,7 +159,6 @@ describe('ol/webgl/WebGLHelper', function () {
});
describe('valid shader compiling', function () {
let h;
let p;
beforeEach(function () {
h = new WebGLHelper();
@@ -189,18 +190,18 @@ describe('ol/webgl/WebGLHelper', function () {
describe('invalid shader compiling', function () {
it('throws for an invalid vertex shader', function () {
const helper = new WebGLHelper();
h = new WebGLHelper();
expect(() =>
helper.getProgram(FRAGMENT_SHADER, INVALID_VERTEX_SHADER)
h.getProgram(FRAGMENT_SHADER, INVALID_VERTEX_SHADER)
).to.throwException(
/Vertex shader compilation failed: ERROR: 0:10: 'bla' : syntax error/
);
});
it('throws for an invalid fragment shader', function () {
const helper = new WebGLHelper();
h = new WebGLHelper();
expect(() =>
helper.getProgram(INVALID_FRAGMENT_SHADER, VERTEX_SHADER)
h.getProgram(INVALID_FRAGMENT_SHADER, VERTEX_SHADER)
).to.throwException(
/Fragment shader compliation failed: ERROR: 0:5: 'oops' : undeclared identifier/
);
@@ -208,7 +209,6 @@ describe('ol/webgl/WebGLHelper', function () {
});
describe('#makeProjectionTransform', function () {
let h;
let frameState;
beforeEach(function () {
h = new WebGLHelper();
@@ -246,20 +246,19 @@ describe('ol/webgl/WebGLHelper', function () {
describe('deleteBuffer()', function () {
it('can be called to free up buffer resources', function () {
const helper = new WebGLHelper();
h = new WebGLHelper();
const buffer = new WebGLArrayBuffer(ARRAY_BUFFER, STATIC_DRAW);
buffer.fromArray([0, 1, 2, 3]);
helper.flushBufferData(buffer);
h.flushBufferData(buffer);
const bufferKey = getUid(buffer);
expect(helper.bufferCache_).to.have.property(bufferKey);
expect(h.bufferCache_).to.have.property(bufferKey);
helper.deleteBuffer(buffer);
expect(helper.bufferCache_).to.not.have.property(bufferKey);
h.deleteBuffer(buffer);
expect(h.bufferCache_).to.not.have.property(bufferKey);
});
});
describe('#createTexture', function () {
let h;
beforeEach(function () {
h = new WebGLHelper();
});
@@ -342,7 +341,7 @@ describe('ol/webgl/WebGLHelper', function () {
});
describe('#enableAttributes', function () {
let baseAttrs, h;
let baseAttrs;
beforeEach(function () {
h = new WebGLHelper();

View File

@@ -17,6 +17,10 @@ describe('ol.webgl.RenderTarget', function () {
}
});
afterEach(function () {
helper.dispose();
});
describe('constructor', function () {
it('creates a target of size 1x1', function () {
const rt = new WebGLRenderTarget(helper);