StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
StackGenVis/frontend/node_modules/gl-fbo/fbo.js

465 lines
12 KiB

'use strict'
var createTexture = require('gl-texture2d')
module.exports = createFBO
var colorAttachmentArrays = null
var FRAMEBUFFER_UNSUPPORTED
var FRAMEBUFFER_INCOMPLETE_ATTACHMENT
var FRAMEBUFFER_INCOMPLETE_DIMENSIONS
var FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
function saveFBOState(gl) {
var fbo = gl.getParameter(gl.FRAMEBUFFER_BINDING)
var rbo = gl.getParameter(gl.RENDERBUFFER_BINDING)
var tex = gl.getParameter(gl.TEXTURE_BINDING_2D)
return [fbo, rbo, tex]
}
function restoreFBOState(gl, data) {
gl.bindFramebuffer(gl.FRAMEBUFFER, data[0])
gl.bindRenderbuffer(gl.RENDERBUFFER, data[1])
gl.bindTexture(gl.TEXTURE_2D, data[2])
}
function lazyInitColorAttachments(gl, ext) {
var maxColorAttachments = gl.getParameter(ext.MAX_COLOR_ATTACHMENTS_WEBGL)
colorAttachmentArrays = new Array(maxColorAttachments + 1)
for(var i=0; i<=maxColorAttachments; ++i) {
var x = new Array(maxColorAttachments)
for(var j=0; j<i; ++j) {
x[j] = gl.COLOR_ATTACHMENT0 + j
}
for(var j=i; j<maxColorAttachments; ++j) {
x[j] = gl.NONE
}
colorAttachmentArrays[i] = x
}
}
//Throw an appropriate error
function throwFBOError(status) {
switch(status){
case FRAMEBUFFER_UNSUPPORTED:
throw new Error('gl-fbo: Framebuffer unsupported')
case FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
throw new Error('gl-fbo: Framebuffer incomplete attachment')
case FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
throw new Error('gl-fbo: Framebuffer incomplete dimensions')
case FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
throw new Error('gl-fbo: Framebuffer incomplete missing attachment')
default:
throw new Error('gl-fbo: Framebuffer failed for unspecified reason')
}
}
//Initialize a texture object
function initTexture(gl, width, height, type, format, attachment) {
if(!type) {
return null
}
var result = createTexture(gl, width, height, format, type)
result.magFilter = gl.NEAREST
result.minFilter = gl.NEAREST
result.mipSamples = 1
result.bind()
gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, result.handle, 0)
return result
}
//Initialize a render buffer object
function initRenderBuffer(gl, width, height, component, attachment) {
var result = gl.createRenderbuffer()
gl.bindRenderbuffer(gl.RENDERBUFFER, result)
gl.renderbufferStorage(gl.RENDERBUFFER, component, width, height)
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, result)
return result
}
//Rebuild the frame buffer
function rebuildFBO(fbo) {
//Save FBO state
var state = saveFBOState(fbo.gl)
var gl = fbo.gl
var handle = fbo.handle = gl.createFramebuffer()
var width = fbo._shape[0]
var height = fbo._shape[1]
var numColors = fbo.color.length
var ext = fbo._ext
var useStencil = fbo._useStencil
var useDepth = fbo._useDepth
var colorType = fbo._colorType
//Bind the fbo
gl.bindFramebuffer(gl.FRAMEBUFFER, handle)
//Allocate color buffers
for(var i=0; i<numColors; ++i) {
fbo.color[i] = initTexture(gl, width, height, colorType, gl.RGBA, gl.COLOR_ATTACHMENT0 + i)
}
if(numColors === 0) {
fbo._color_rb = initRenderBuffer(gl, width, height, gl.RGBA4, gl.COLOR_ATTACHMENT0)
if(ext) {
ext.drawBuffersWEBGL(colorAttachmentArrays[0])
}
} else if(numColors > 1) {
ext.drawBuffersWEBGL(colorAttachmentArrays[numColors])
}
//Allocate depth/stencil buffers
var WEBGL_depth_texture = gl.getExtension('WEBGL_depth_texture')
if(WEBGL_depth_texture) {
if(useStencil) {
fbo.depth = initTexture(gl, width, height,
WEBGL_depth_texture.UNSIGNED_INT_24_8_WEBGL,
gl.DEPTH_STENCIL,
gl.DEPTH_STENCIL_ATTACHMENT)
} else if(useDepth) {
fbo.depth = initTexture(gl, width, height,
gl.UNSIGNED_SHORT,
gl.DEPTH_COMPONENT,
gl.DEPTH_ATTACHMENT)
}
} else {
if(useDepth && useStencil) {
fbo._depth_rb = initRenderBuffer(gl, width, height, gl.DEPTH_STENCIL, gl.DEPTH_STENCIL_ATTACHMENT)
} else if(useDepth) {
fbo._depth_rb = initRenderBuffer(gl, width, height, gl.DEPTH_COMPONENT16, gl.DEPTH_ATTACHMENT)
} else if(useStencil) {
fbo._depth_rb = initRenderBuffer(gl, width, height, gl.STENCIL_INDEX, gl.STENCIL_ATTACHMENT)
}
}
//Check frame buffer state
var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER)
if(status !== gl.FRAMEBUFFER_COMPLETE) {
//Release all partially allocated resources
fbo._destroyed = true
//Release all resources
gl.bindFramebuffer(gl.FRAMEBUFFER, null)
gl.deleteFramebuffer(fbo.handle)
fbo.handle = null
if(fbo.depth) {
fbo.depth.dispose()
fbo.depth = null
}
if(fbo._depth_rb) {
gl.deleteRenderbuffer(fbo._depth_rb)
fbo._depth_rb = null
}
for(var i=0; i<fbo.color.length; ++i) {
fbo.color[i].dispose()
fbo.color[i] = null
}
if(fbo._color_rb) {
gl.deleteRenderbuffer(fbo._color_rb)
fbo._color_rb = null
}
restoreFBOState(gl, state)
//Throw the frame buffer error
throwFBOError(status)
}
//Everything ok, let's get on with life
restoreFBOState(gl, state)
}
function Framebuffer(gl, width, height, colorType, numColors, useDepth, useStencil, ext) {
//Handle and set properties
this.gl = gl
this._shape = [width|0, height|0]
this._destroyed = false
this._ext = ext
//Allocate buffers
this.color = new Array(numColors)
for(var i=0; i<numColors; ++i) {
this.color[i] = null
}
this._color_rb = null
this.depth = null
this._depth_rb = null
//Save depth and stencil flags
this._colorType = colorType
this._useDepth = useDepth
this._useStencil = useStencil
//Shape vector for resizing
var parent = this
var shapeVector = [width|0, height|0]
Object.defineProperties(shapeVector, {
0: {
get: function() {
return parent._shape[0]
},
set: function(w) {
return parent.width = w
}
},
1: {
get: function() {
return parent._shape[1]
},
set: function(h) {
return parent.height = h
}
}
})
this._shapeVector = shapeVector
//Initialize all attachments
rebuildFBO(this)
}
var proto = Framebuffer.prototype
function reshapeFBO(fbo, w, h) {
//If fbo is invalid, just skip this
if(fbo._destroyed) {
throw new Error('gl-fbo: Can\'t resize destroyed FBO')
}
//Don't resize if no change in shape
if( (fbo._shape[0] === w) &&
(fbo._shape[1] === h) ) {
return
}
var gl = fbo.gl
//Check parameter ranges
var maxFBOSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE)
if( w < 0 || w > maxFBOSize ||
h < 0 || h > maxFBOSize) {
throw new Error('gl-fbo: Can\'t resize FBO, invalid dimensions')
}
//Update shape
fbo._shape[0] = w
fbo._shape[1] = h
//Save framebuffer state
var state = saveFBOState(gl)
//Resize framebuffer attachments
for(var i=0; i<fbo.color.length; ++i) {
fbo.color[i].shape = fbo._shape
}
if(fbo._color_rb) {
gl.bindRenderbuffer(gl.RENDERBUFFER, fbo._color_rb)
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, fbo._shape[0], fbo._shape[1])
}
if(fbo.depth) {
fbo.depth.shape = fbo._shape
}
if(fbo._depth_rb) {
gl.bindRenderbuffer(gl.RENDERBUFFER, fbo._depth_rb)
if(fbo._useDepth && fbo._useStencil) {
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, fbo._shape[0], fbo._shape[1])
} else if(fbo._useDepth) {
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, fbo._shape[0], fbo._shape[1])
} else if(fbo._useStencil) {
gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX, fbo._shape[0], fbo._shape[1])
}
}
//Check FBO status after resize, if something broke then die in a fire
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.handle)
var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER)
if(status !== gl.FRAMEBUFFER_COMPLETE) {
fbo.dispose()
restoreFBOState(gl, state)
throwFBOError(status)
}
//Restore framebuffer state
restoreFBOState(gl, state)
}
Object.defineProperties(proto, {
'shape': {
get: function() {
if(this._destroyed) {
return [0,0]
}
return this._shapeVector
},
set: function(x) {
if(!Array.isArray(x)) {
x = [x|0, x|0]
}
if(x.length !== 2) {
throw new Error('gl-fbo: Shape vector must be length 2')
}
var w = x[0]|0
var h = x[1]|0
reshapeFBO(this, w, h)
return [w, h]
},
enumerable: false
},
'width': {
get: function() {
if(this._destroyed) {
return 0
}
return this._shape[0]
},
set: function(w) {
w = w|0
reshapeFBO(this, w, this._shape[1])
return w
},
enumerable: false
},
'height': {
get: function() {
if(this._destroyed) {
return 0
}
return this._shape[1]
},
set: function(h) {
h = h|0
reshapeFBO(this, this._shape[0], h)
return h
},
enumerable: false
}
})
proto.bind = function() {
if(this._destroyed) {
return
}
var gl = this.gl
gl.bindFramebuffer(gl.FRAMEBUFFER, this.handle)
gl.viewport(0, 0, this._shape[0], this._shape[1])
}
proto.dispose = function() {
if(this._destroyed) {
return
}
this._destroyed = true
var gl = this.gl
gl.deleteFramebuffer(this.handle)
this.handle = null
if(this.depth) {
this.depth.dispose()
this.depth = null
}
if(this._depth_rb) {
gl.deleteRenderbuffer(this._depth_rb)
this._depth_rb = null
}
for(var i=0; i<this.color.length; ++i) {
this.color[i].dispose()
this.color[i] = null
}
if(this._color_rb) {
gl.deleteRenderbuffer(this._color_rb)
this._color_rb = null
}
}
function createFBO(gl, width, height, options) {
//Update frame buffer error code values
if(!FRAMEBUFFER_UNSUPPORTED) {
FRAMEBUFFER_UNSUPPORTED = gl.FRAMEBUFFER_UNSUPPORTED
FRAMEBUFFER_INCOMPLETE_ATTACHMENT = gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT
FRAMEBUFFER_INCOMPLETE_DIMENSIONS = gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS
FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
}
//Lazily initialize color attachment arrays
var WEBGL_draw_buffers = gl.getExtension('WEBGL_draw_buffers')
if(!colorAttachmentArrays && WEBGL_draw_buffers) {
lazyInitColorAttachments(gl, WEBGL_draw_buffers)
}
//Special case: Can accept an array as argument
if(Array.isArray(width)) {
options = height
height = width[1]|0
width = width[0]|0
}
if(typeof width !== 'number') {
throw new Error('gl-fbo: Missing shape parameter')
}
//Validate width/height properties
var maxFBOSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE)
if(width < 0 || width > maxFBOSize || height < 0 || height > maxFBOSize) {
throw new Error('gl-fbo: Parameters are too large for FBO')
}
//Handle each option type
options = options || {}
//Figure out number of color buffers to use
var numColors = 1
if('color' in options) {
numColors = Math.max(options.color|0, 0)
if(numColors < 0) {
throw new Error('gl-fbo: Must specify a nonnegative number of colors')
}
if(numColors > 1) {
//Check if multiple render targets supported
if(!WEBGL_draw_buffers) {
throw new Error('gl-fbo: Multiple draw buffer extension not supported')
} else if(numColors > gl.getParameter(WEBGL_draw_buffers.MAX_COLOR_ATTACHMENTS_WEBGL)) {
throw new Error('gl-fbo: Context does not support ' + numColors + ' draw buffers')
}
}
}
//Determine whether to use floating point textures
var colorType = gl.UNSIGNED_BYTE
var OES_texture_float = gl.getExtension('OES_texture_float')
if(options.float && numColors > 0) {
if(!OES_texture_float) {
throw new Error('gl-fbo: Context does not support floating point textures')
}
colorType = gl.FLOAT
} else if(options.preferFloat && numColors > 0) {
if(OES_texture_float) {
colorType = gl.FLOAT
}
}
//Check if we should use depth buffer
var useDepth = true
if('depth' in options) {
useDepth = !!options.depth
}
//Check if we should use a stencil buffer
var useStencil = false
if('stencil' in options) {
useStencil = !!options.stencil
}
return new Framebuffer(
gl,
width,
height,
colorType,
numColors,
useDepth,
useStencil,
WEBGL_draw_buffers)
}