/** * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose */ import { Program } from './program'; import { ElementsBuffer, AttributeBuffers } from './buffer'; import { WebGLExtensions } from './extensions'; import { idFactory } from '../../mol-util/id-factory'; const getNextVertexArrayId = idFactory(); function getVertexArray(extensions: WebGLExtensions): WebGLVertexArrayObject { const { vertexArrayObject } = extensions; if (!vertexArrayObject) { throw new Error('VertexArrayObject not supported'); } const vertexArray = vertexArrayObject.createVertexArray(); if (!vertexArray) { throw new Error('Could not create WebGL vertex array'); } return vertexArray; } function getVertexArrayObject(extensions: WebGLExtensions) { const { vertexArrayObject } = extensions; if (vertexArrayObject === null) { throw new Error('VertexArrayObject not supported'); } return vertexArrayObject; } export interface VertexArray { readonly id: number bind: () => void update: () => void reset: () => void destroy: () => void } export function createVertexArray(extensions: WebGLExtensions, program: Program, attributeBuffers: AttributeBuffers, elementsBuffer?: ElementsBuffer): VertexArray { const id = getNextVertexArrayId(); let vertexArray = getVertexArray(extensions); let vertexArrayObject = getVertexArrayObject(extensions); function update() { vertexArrayObject.bindVertexArray(vertexArray); if (elementsBuffer) elementsBuffer.bind(); program.bindAttributes(attributeBuffers); vertexArrayObject.bindVertexArray(null); } update(); let destroyed = false; return { id, bind: () => { vertexArrayObject.bindVertexArray(vertexArray); }, update, reset: () => { vertexArray = getVertexArray(extensions); vertexArrayObject = getVertexArrayObject(extensions); update(); }, destroy: () => { if (destroyed) return; vertexArrayObject.deleteVertexArray(vertexArray); destroyed = true; } }; }