UNPKG

@luma.gl/gltools

Version:

WebGL2 API Polyfills for WebGL1 WebGLRenderingContext

167 lines (136 loc) 4.04 kB
import { GL_PARAMETER_DEFAULTS, GL_HOOKED_SETTERS } from './webgl-parameter-tables'; import { setParameters, getParameters } from './unified-parameter-api'; import { assert } from '../utils/assert'; import { deepArrayEqual } from '../utils/utils'; function installGetterOverride(gl, functionName) { const originalGetterFunc = gl[functionName].bind(gl); gl[functionName] = function get() { const pname = arguments.length <= 0 ? undefined : arguments[0]; if (!(pname in gl.state.cache)) { return originalGetterFunc(...arguments); } return gl.state.enable ? gl.state.cache[pname] : originalGetterFunc(...arguments); }; Object.defineProperty(gl[functionName], 'name', { value: "".concat(functionName, "-from-cache"), configurable: false }); } function installSetterSpy(gl, functionName, setter) { const originalSetterFunc = gl[functionName].bind(gl); gl[functionName] = function set() { for (var _len = arguments.length, params = new Array(_len), _key = 0; _key < _len; _key++) { params[_key] = arguments[_key]; } const { valueChanged, oldValue } = setter(gl.state._updateCache, ...params); if (valueChanged) { originalSetterFunc(...params); } return oldValue; }; Object.defineProperty(gl[functionName], 'name', { value: "".concat(functionName, "-to-cache"), configurable: false }); } function installProgramSpy(gl) { const originalUseProgram = gl.useProgram.bind(gl); gl.useProgram = function useProgramLuma(handle) { if (gl.state.program !== handle) { originalUseProgram(handle); gl.state.program = handle; } }; } class GLState { constructor(gl) { let { copyState = false, log = () => {} } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; this.gl = gl; this.program = null; this.stateStack = []; this.enable = true; this.cache = copyState ? getParameters(gl) : Object.assign({}, GL_PARAMETER_DEFAULTS); this.log = log; this._updateCache = this._updateCache.bind(this); Object.seal(this); } push() { let values = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; this.stateStack.push({}); } pop() { assert(this.stateStack.length > 0); const oldValues = this.stateStack[this.stateStack.length - 1]; setParameters(this.gl, oldValues); this.stateStack.pop(); } _updateCache(values) { let valueChanged = false; let oldValue; const oldValues = this.stateStack.length > 0 && this.stateStack[this.stateStack.length - 1]; for (const key in values) { assert(key !== undefined); const value = values[key]; const cached = this.cache[key]; if (!deepArrayEqual(value, cached)) { valueChanged = true; oldValue = cached; if (oldValues && !(key in oldValues)) { oldValues[key] = cached; } this.cache[key] = value; } } return { valueChanged, oldValue }; } } export function trackContextState(gl) { let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; const { enable = true, copyState } = options; assert(copyState !== undefined); if (!gl.state) { const { polyfillContext } = globalThis; if (polyfillContext) { polyfillContext(gl); } gl.state = new GLState(gl, { copyState }); installProgramSpy(gl); for (const key in GL_HOOKED_SETTERS) { const setter = GL_HOOKED_SETTERS[key]; installSetterSpy(gl, key, setter); } installGetterOverride(gl, 'getParameter'); installGetterOverride(gl, 'isEnabled'); } gl.state.enable = enable; return gl; } export function pushContextState(gl) { if (!gl.state) { trackContextState(gl, { copyState: false }); } gl.state.push(); } export function popContextState(gl) { assert(gl.state); gl.state.pop(); } //# sourceMappingURL=track-context-state.js.map