Manage buffers in WebGL map renderer

This commit is contained in:
Tom Payne
2013-03-21 00:18:28 +01:00
parent ecd5158012
commit cc41d720fa
3 changed files with 91 additions and 50 deletions

View File

@@ -132,19 +132,6 @@ ol.renderer.webgl.Layer.prototype.bindFramebuffer =
};
/**
* @inheritDoc
*/
ol.renderer.webgl.Layer.prototype.disposeInternal = function() {
var mapRenderer = this.getWebGLMapRenderer();
var gl = mapRenderer.getGL();
if (!gl.isContextLost()) {
gl.deleteBuffer(this.arrayBuffer_);
}
goog.base(this, 'disposeInternal');
};
/**
* @return {!goog.vec.Mat4.Float32} Color matrix.
*/

View File

@@ -22,6 +22,7 @@ goog.require('ol.renderer.webgl.FragmentShader');
goog.require('ol.renderer.webgl.ImageLayer');
goog.require('ol.renderer.webgl.TileLayer');
goog.require('ol.renderer.webgl.VertexShader');
goog.require('ol.structs.Buffer');
goog.require('ol.structs.LRUCache');
goog.require('ol.webgl');
goog.require('ol.webgl.WebGLContextEventType');
@@ -33,6 +34,12 @@ goog.require('ol.webgl.WebGLContextEventType');
ol.WEBGL_TEXTURE_CACHE_HIGH_WATER_MARK = 1024;
/**
* @typedef {{buffer: WebGLBuffer}}
*/
ol.renderer.webgl.BufferCacheEntry;
/**
* @typedef {{magFilter: number, minFilter: number, texture: WebGLTexture}}
*/
@@ -170,9 +177,20 @@ ol.renderer.webgl.Map = function(container, map) {
/**
* @private
* @type {WebGLBuffer}
* @type {ol.structs.Buffer}
*/
this.arrayBuffer_ = null;
this.arrayBuffer_ = new ol.structs.Buffer([
-1, -1, 0, 0,
1, -1, 1, 0,
-1, 1, 0, 1,
1, 1, 1, 1
]);
/**
* @private
* @type {Object.<number, ol.renderer.webgl.BufferCacheEntry>}
*/
this.bufferCache_ = {};
/**
* @private
@@ -216,6 +234,46 @@ ol.renderer.webgl.Map = function(container, map) {
goog.inherits(ol.renderer.webgl.Map, ol.renderer.Map);
/**
* @param {number} target Target.
* @param {ol.structs.Buffer} buf Buffer.
*/
ol.renderer.webgl.Map.prototype.bindBuffer = function(target, buf) {
var gl = this.getGL();
var arr = buf.getArray();
// FIXME dirty set should be in buffer cache
var dirtySet = buf.getDirtySet();
var bufferKey = goog.getUid(buf);
if (bufferKey in this.bufferCache_) {
var bufferCacheEntry = this.bufferCache_[bufferKey];
gl.bindBuffer(target, bufferCacheEntry.buffer);
dirtySet.forEachRange(function(start, stop) {
// FIXME check if slice is really efficient here
var slice = arr.slice(start, stop);
gl.bufferSubData(
target,
start,
target == goog.webgl.ARRAY_BUFFER ?
new Float32Array(slice) :
new Uint16Array(slice));
});
} else {
var buffer = gl.createBuffer();
gl.bindBuffer(target, buffer);
// FIXME should get STATIC/STREAM from buf
gl.bufferData(
target,
target == goog.webgl.ARRAY_BUFFER ?
new Float32Array(arr) : new Uint16Array(arr),
goog.webgl.STATIC_DRAW);
this.bufferCache_[bufferKey] = {
buffer: buffer
};
}
dirtySet.clear();
};
/**
* @param {ol.Tile} tile Tile.
* @param {number} magFilter Mag filter.
@@ -276,12 +334,31 @@ ol.renderer.webgl.Map.prototype.createLayerRenderer = function(layer) {
};
/**
* @param {ol.structs.Buffer} buf Buffer.
*/
ol.renderer.webgl.Map.prototype.deleteBuffer = function(buf) {
var gl = this.getGL();
var arr = buf.getArray();
var bufferKey = goog.getUid(buf);
goog.asserts.assert(bufferKey in this.bufferCache_);
var bufferCacheEntry = this.bufferCache_[bufferKey];
if (!gl.isContextLost()) {
gl.deleteBuffer(bufferCacheEntry.buffer);
}
delete this.bufferCache_[bufferKey];
};
/**
* @inheritDoc
*/
ol.renderer.webgl.Map.prototype.disposeInternal = function() {
var gl = this.getGL();
if (!gl.isContextLost()) {
goog.object.forEach(this.bufferCache_, function(bufferCacheEntry) {
gl.deleteBuffer(bufferCacheEntry.buffer);
});
goog.object.forEach(this.programCache_, function(program) {
gl.deleteProgram(program);
});
@@ -409,7 +486,7 @@ ol.renderer.webgl.Map.prototype.handleWebGLContextLost = function(event) {
}
event.preventDefault();
this.locations_ = null;
this.arrayBuffer_ = null;
this.bufferCache_ = {};
this.shaderCache_ = {};
this.programCache_ = {};
this.textureCache_.clear();
@@ -511,19 +588,7 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
};
}
if (goog.isNull(this.arrayBuffer_)) {
var arrayBuffer = gl.createBuffer();
gl.bindBuffer(goog.webgl.ARRAY_BUFFER, arrayBuffer);
gl.bufferData(goog.webgl.ARRAY_BUFFER, new Float32Array([
-1, -1, 0, 0,
1, -1, 1, 0,
-1, 1, 0, 1,
1, 1, 1, 1
]), goog.webgl.STATIC_DRAW);
this.arrayBuffer_ = arrayBuffer;
} else {
gl.bindBuffer(goog.webgl.ARRAY_BUFFER, this.arrayBuffer_);
}
this.bindBuffer(goog.webgl.ARRAY_BUFFER, this.arrayBuffer_);
gl.enableVertexAttribArray(this.locations_.a_position);
gl.vertexAttribPointer(

View File

@@ -23,6 +23,7 @@ goog.require('ol.math');
goog.require('ol.renderer.webgl.FragmentShader');
goog.require('ol.renderer.webgl.Layer');
goog.require('ol.renderer.webgl.VertexShader');
goog.require('ol.structs.Buffer');
@@ -113,9 +114,14 @@ ol.renderer.webgl.TileLayer = function(mapRenderer, tileLayer) {
/**
* @private
* @type {WebGLBuffer}
* @type {ol.structs.Buffer}
*/
this.arrayBuffer_ = null;
this.arrayBuffer_ = new ol.structs.Buffer([
0, 0, 0, 1,
1, 0, 1, 1,
0, 1, 0, 0,
1, 1, 1, 0
]);
/**
* @private
@@ -150,10 +156,7 @@ goog.inherits(ol.renderer.webgl.TileLayer, ol.renderer.webgl.Layer);
*/
ol.renderer.webgl.TileLayer.prototype.disposeInternal = function() {
var mapRenderer = this.getWebGLMapRenderer();
var gl = mapRenderer.getGL();
if (!gl.isContextLost()) {
gl.deleteBuffer(this.arrayBuffer_);
}
mapRenderer.deleteBuffer(this.arrayBuffer_);
goog.base(this, 'disposeInternal');
};
@@ -188,7 +191,6 @@ ol.renderer.webgl.TileLayer.prototype.getTileLayer = function() {
ol.renderer.webgl.TileLayer.prototype.handleWebGLContextLost = function() {
goog.base(this, 'handleWebGLContextLost');
this.locations_ = null;
this.arrayBuffer_ = null;
};
@@ -269,20 +271,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame =
};
}
if (goog.isNull(this.arrayBuffer_)) {
var arrayBuffer = gl.createBuffer();
gl.bindBuffer(goog.webgl.ARRAY_BUFFER, arrayBuffer);
gl.bufferData(goog.webgl.ARRAY_BUFFER, new Float32Array([
0, 0, 0, 1,
1, 0, 1, 1,
0, 1, 0, 0,
1, 1, 1, 0
]), goog.webgl.STATIC_DRAW);
this.arrayBuffer_ = arrayBuffer;
} else {
gl.bindBuffer(goog.webgl.ARRAY_BUFFER, this.arrayBuffer_);
}
mapRenderer.bindBuffer(goog.webgl.ARRAY_BUFFER, this.arrayBuffer_);
gl.enableVertexAttribArray(this.locations_.aPosition);
gl.vertexAttribPointer(
this.locations_.aPosition, 2, goog.webgl.FLOAT, false, 16, 0);