const bits = require('bit-twiddle') const { WebGLContextAttributes } = require('./webgl-context-attributes') const { WebGLRenderingContext, wrapContext } = require('./webgl-rendering-context') const { WebGLTextureUnit } = require('./webgl-texture-unit') const { WebGLVertexArrayObjectState, WebGLVertexArrayGlobalState } = require('./webgl-vertex-attribute') let CONTEXT_COUNTER = 0 function flag (options, name, dflt) { if (!options || !(typeof options === 'object') || !(name in options)) { return dflt } return !!options[name] } function createContext (width, height, options) { width = width | 0 height = height | 0 if (!(width > 0 && height > 0)) { return null } const contextAttributes = new WebGLContextAttributes( flag(options, 'alpha', true), flag(options, 'depth', true), flag(options, 'stencil', false), false, // flag(options, 'antialias', true), flag(options, 'premultipliedAlpha', true), flag(options, 'preserveDrawingBuffer', false), flag(options, 'preferLowPowerToHighPerformance', false), flag(options, 'failIfMajorPerformanceCaveat', false)) // Can only use premultipliedAlpha if alpha is set contextAttributes.premultipliedAlpha = contextAttributes.premultipliedAlpha && contextAttributes.alpha let ctx try { ctx = new WebGLRenderingContext( 1, 1, contextAttributes.alpha, contextAttributes.depth, contextAttributes.stencil, contextAttributes.antialias, contextAttributes.premultipliedAlpha, contextAttributes.preserveDrawingBuffer, contextAttributes.preferLowPowerToHighPerformance, contextAttributes.failIfMajorPerformanceCaveat) } catch (e) {} if (!ctx) { return null } ctx.drawingBufferWidth = width ctx.drawingBufferHeight = height ctx._ = CONTEXT_COUNTER++ ctx._contextAttributes = contextAttributes ctx._extensions = {} ctx._programs = {} ctx._shaders = {} ctx._buffers = {} ctx._textures = {} ctx._framebuffers = {} ctx._renderbuffers = {} ctx._activeProgram = null ctx._activeFramebuffer = null ctx._activeRenderbuffer = null ctx._checkStencil = false ctx._stencilState = true // Initialize texture units const numTextures = ctx.getParameter(ctx.MAX_COMBINED_TEXTURE_IMAGE_UNITS) ctx._textureUnits = new Array(numTextures) for (let i = 0; i < numTextures; ++i) { ctx._textureUnits[i] = new WebGLTextureUnit(i) } ctx._activeTextureUnit = 0 ctx.activeTexture(ctx.TEXTURE0) ctx._errorStack = [] // Vertex array attributes that are in vertex array objects. ctx._defaultVertexObjectState = new WebGLVertexArrayObjectState(ctx) ctx._vertexObjectState = ctx._defaultVertexObjectState // Vertex array attibures that are not in vertex array objects. ctx._vertexGlobalState = new WebGLVertexArrayGlobalState(ctx) // Store limits ctx._maxTextureSize = ctx.getParameter(ctx.MAX_TEXTURE_SIZE) ctx._maxTextureLevel = bits.log2(bits.nextPow2(ctx._maxTextureSize)) ctx._maxCubeMapSize = ctx.getParameter(ctx.MAX_CUBE_MAP_TEXTURE_SIZE) ctx._maxCubeMapLevel = bits.log2(bits.nextPow2(ctx._maxCubeMapSize)) // Unpack alignment ctx._unpackAlignment = 4 ctx._packAlignment = 4 // Allocate framebuffer ctx._allocateDrawingBuffer(width, height) const attrib0Buffer = ctx.createBuffer() ctx._attrib0Buffer = attrib0Buffer // Initialize defaults ctx.bindBuffer(ctx.ARRAY_BUFFER, null) ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, null) ctx.bindFramebuffer(ctx.FRAMEBUFFER, null) ctx.bindRenderbuffer(ctx.RENDERBUFFER, null) // Set viewport and scissor ctx.viewport(0, 0, width, height) ctx.scissor(0, 0, width, height) // Clear buffers ctx.clearDepth(1) ctx.clearColor(0, 0, 0, 0) ctx.clearStencil(0) ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT | ctx.STENCIL_BUFFER_BIT) return wrapContext(ctx) } module.exports = createContext