securityos/node_modules/regl/lib/renderbuffer.js

256 lines
6.5 KiB
JavaScript

var check = require('./util/check')
var values = require('./util/values')
var GL_RENDERBUFFER = 0x8D41
var GL_RGBA4 = 0x8056
var GL_RGB5_A1 = 0x8057
var GL_RGB565 = 0x8D62
var GL_DEPTH_COMPONENT16 = 0x81A5
var GL_STENCIL_INDEX8 = 0x8D48
var GL_DEPTH_STENCIL = 0x84F9
var GL_SRGB8_ALPHA8_EXT = 0x8C43
var GL_RGBA32F_EXT = 0x8814
var GL_RGBA16F_EXT = 0x881A
var GL_RGB16F_EXT = 0x881B
var FORMAT_SIZES = []
FORMAT_SIZES[GL_RGBA4] = 2
FORMAT_SIZES[GL_RGB5_A1] = 2
FORMAT_SIZES[GL_RGB565] = 2
FORMAT_SIZES[GL_DEPTH_COMPONENT16] = 2
FORMAT_SIZES[GL_STENCIL_INDEX8] = 1
FORMAT_SIZES[GL_DEPTH_STENCIL] = 4
FORMAT_SIZES[GL_SRGB8_ALPHA8_EXT] = 4
FORMAT_SIZES[GL_RGBA32F_EXT] = 16
FORMAT_SIZES[GL_RGBA16F_EXT] = 8
FORMAT_SIZES[GL_RGB16F_EXT] = 6
function getRenderbufferSize (format, width, height) {
return FORMAT_SIZES[format] * width * height
}
module.exports = function (gl, extensions, limits, stats, config) {
var formatTypes = {
'rgba4': GL_RGBA4,
'rgb565': GL_RGB565,
'rgb5 a1': GL_RGB5_A1,
'depth': GL_DEPTH_COMPONENT16,
'stencil': GL_STENCIL_INDEX8,
'depth stencil': GL_DEPTH_STENCIL
}
if (extensions.ext_srgb) {
formatTypes['srgba'] = GL_SRGB8_ALPHA8_EXT
}
if (extensions.ext_color_buffer_half_float) {
formatTypes['rgba16f'] = GL_RGBA16F_EXT
formatTypes['rgb16f'] = GL_RGB16F_EXT
}
if (extensions.webgl_color_buffer_float) {
formatTypes['rgba32f'] = GL_RGBA32F_EXT
}
var formatTypesInvert = []
Object.keys(formatTypes).forEach(function (key) {
var val = formatTypes[key]
formatTypesInvert[val] = key
})
var renderbufferCount = 0
var renderbufferSet = {}
function REGLRenderbuffer (renderbuffer) {
this.id = renderbufferCount++
this.refCount = 1
this.renderbuffer = renderbuffer
this.format = GL_RGBA4
this.width = 0
this.height = 0
if (config.profile) {
this.stats = { size: 0 }
}
}
REGLRenderbuffer.prototype.decRef = function () {
if (--this.refCount <= 0) {
destroy(this)
}
}
function destroy (rb) {
var handle = rb.renderbuffer
check(handle, 'must not double destroy renderbuffer')
gl.bindRenderbuffer(GL_RENDERBUFFER, null)
gl.deleteRenderbuffer(handle)
rb.renderbuffer = null
rb.refCount = 0
delete renderbufferSet[rb.id]
stats.renderbufferCount--
}
function createRenderbuffer (a, b) {
var renderbuffer = new REGLRenderbuffer(gl.createRenderbuffer())
renderbufferSet[renderbuffer.id] = renderbuffer
stats.renderbufferCount++
function reglRenderbuffer (a, b) {
var w = 0
var h = 0
var format = GL_RGBA4
if (typeof a === 'object' && a) {
var options = a
if ('shape' in options) {
var shape = options.shape
check(Array.isArray(shape) && shape.length >= 2,
'invalid renderbuffer shape')
w = shape[0] | 0
h = shape[1] | 0
} else {
if ('radius' in options) {
w = h = options.radius | 0
}
if ('width' in options) {
w = options.width | 0
}
if ('height' in options) {
h = options.height | 0
}
}
if ('format' in options) {
check.parameter(options.format, formatTypes,
'invalid renderbuffer format')
format = formatTypes[options.format]
}
} else if (typeof a === 'number') {
w = a | 0
if (typeof b === 'number') {
h = b | 0
} else {
h = w
}
} else if (!a) {
w = h = 1
} else {
check.raise('invalid arguments to renderbuffer constructor')
}
// check shape
check(
w > 0 && h > 0 &&
w <= limits.maxRenderbufferSize && h <= limits.maxRenderbufferSize,
'invalid renderbuffer size')
if (w === renderbuffer.width &&
h === renderbuffer.height &&
format === renderbuffer.format) {
return
}
reglRenderbuffer.width = renderbuffer.width = w
reglRenderbuffer.height = renderbuffer.height = h
renderbuffer.format = format
gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer.renderbuffer)
gl.renderbufferStorage(GL_RENDERBUFFER, format, w, h)
check(
gl.getError() === 0,
'invalid render buffer format')
if (config.profile) {
renderbuffer.stats.size = getRenderbufferSize(renderbuffer.format, renderbuffer.width, renderbuffer.height)
}
reglRenderbuffer.format = formatTypesInvert[renderbuffer.format]
return reglRenderbuffer
}
function resize (w_, h_) {
var w = w_ | 0
var h = (h_ | 0) || w
if (w === renderbuffer.width && h === renderbuffer.height) {
return reglRenderbuffer
}
// check shape
check(
w > 0 && h > 0 &&
w <= limits.maxRenderbufferSize && h <= limits.maxRenderbufferSize,
'invalid renderbuffer size')
reglRenderbuffer.width = renderbuffer.width = w
reglRenderbuffer.height = renderbuffer.height = h
gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer.renderbuffer)
gl.renderbufferStorage(GL_RENDERBUFFER, renderbuffer.format, w, h)
check(
gl.getError() === 0,
'invalid render buffer format')
// also, recompute size.
if (config.profile) {
renderbuffer.stats.size = getRenderbufferSize(
renderbuffer.format, renderbuffer.width, renderbuffer.height)
}
return reglRenderbuffer
}
reglRenderbuffer(a, b)
reglRenderbuffer.resize = resize
reglRenderbuffer._reglType = 'renderbuffer'
reglRenderbuffer._renderbuffer = renderbuffer
if (config.profile) {
reglRenderbuffer.stats = renderbuffer.stats
}
reglRenderbuffer.destroy = function () {
renderbuffer.decRef()
}
return reglRenderbuffer
}
if (config.profile) {
stats.getTotalRenderbufferSize = function () {
var total = 0
Object.keys(renderbufferSet).forEach(function (key) {
total += renderbufferSet[key].stats.size
})
return total
}
}
function restoreRenderbuffers () {
values(renderbufferSet).forEach(function (rb) {
rb.renderbuffer = gl.createRenderbuffer()
gl.bindRenderbuffer(GL_RENDERBUFFER, rb.renderbuffer)
gl.renderbufferStorage(GL_RENDERBUFFER, rb.format, rb.width, rb.height)
})
gl.bindRenderbuffer(GL_RENDERBUFFER, null)
}
return {
create: createRenderbuffer,
clear: function () {
values(renderbufferSet).forEach(destroy)
},
restore: restoreRenderbuffers
}
}