@luma.gl/webgl2-polyfill
Advanced tools
Comparing version 7.0.0-alpha.14 to 7.0.0-alpha.15
@@ -10,184 +10,27 @@ "use strict"; | ||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); | ||
var _assert = _interopRequireDefault(require("./assert")); | ||
var _polyfillGetParameter = require("./polyfill-get-parameter"); | ||
var _polyfillTable = require("./polyfill-table"); | ||
var _WEBGL_CONTEXT_POLYFI; | ||
function polyfillContext(gl) { | ||
gl.luma = gl.luma || {}; | ||
initializeExtensions(gl); | ||
function assert(condition, message) { | ||
if (!condition) { | ||
throw new Error(message || 'luma.gl: assertion failed.'); | ||
if (!gl.luma.polyfilled) { | ||
installPolyfills(gl, _polyfillTable.WEBGL2_CONTEXT_POLYFILLS); | ||
installOverrides(gl, { | ||
target: gl.luma, | ||
target2: gl | ||
}); | ||
gl.luma.polyfilled = true; | ||
} | ||
return gl; | ||
} | ||
var OES_vertex_array_object = 'OES_vertex_array_object'; | ||
var ANGLE_instanced_arrays = 'ANGLE_instanced_arrays'; | ||
var WEBGL_draw_buffers = 'WEBGL_draw_buffers'; | ||
var EXT_disjoint_timer_query = 'EXT_disjoint_timer_query'; | ||
var EXT_texture_filter_anisotropic = 'EXT_texture_filter_anisotropic'; | ||
var ERR_VAO_NOT_SUPPORTED = 'VertexArray requires WebGL2 or OES_vertex_array_object extension'; // Return true if WebGL2 context | ||
var global_ = typeof global !== 'undefined' ? global : window; | ||
global_.polyfillContext = polyfillContext; | ||
function isWebGL2(gl) { | ||
return gl && 32874 === 32874; | ||
} // Return object with webgl2 flag and an extension | ||
function getExtensionData(gl, extension) { | ||
return { | ||
webgl2: isWebGL2(gl), | ||
ext: gl.getExtension(extension) | ||
}; | ||
} // function mapExtensionConstant(gl, constant) { | ||
// switch (constant) { | ||
// case ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES: return GL.FRAGMENT_SHADER_DERIVATIVE_HINT; | ||
// } | ||
// } | ||
var WEBGL_CONTEXT_POLYFILLS = (_WEBGL_CONTEXT_POLYFI = {}, (0, _defineProperty2.default)(_WEBGL_CONTEXT_POLYFI, OES_vertex_array_object, { | ||
meta: { | ||
suffix: 'OES' | ||
}, | ||
// NEW METHODS | ||
createVertexArray: function createVertexArray() { | ||
assert(false, ERR_VAO_NOT_SUPPORTED); | ||
}, | ||
deleteVertexArray: function deleteVertexArray() {}, | ||
bindVertexArray: function bindVertexArray() {}, | ||
isVertexArray: function isVertexArray() { | ||
return false; | ||
} | ||
}), (0, _defineProperty2.default)(_WEBGL_CONTEXT_POLYFI, ANGLE_instanced_arrays, { | ||
meta: { | ||
suffix: 'ANGLE' // constants: { | ||
// VERTEX_ATTRIB_ARRAY_DIVISOR: 'VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE' | ||
// } | ||
}, | ||
vertexAttribDivisor: function vertexAttribDivisor(location, divisor) { | ||
// Accept divisor 0 even if instancing is not supported (0 = no instancing) | ||
assert(divisor === 0, 'WebGL instanced rendering not supported'); | ||
}, | ||
drawElementsInstanced: function drawElementsInstanced() {}, | ||
drawArraysInstanced: function drawArraysInstanced() {} | ||
}), (0, _defineProperty2.default)(_WEBGL_CONTEXT_POLYFI, WEBGL_draw_buffers, { | ||
meta: { | ||
suffix: 'WEBGL' | ||
}, | ||
drawBuffers: function drawBuffers() { | ||
assert(false); | ||
} | ||
}), (0, _defineProperty2.default)(_WEBGL_CONTEXT_POLYFI, EXT_disjoint_timer_query, { | ||
meta: { | ||
suffix: 'EXT' | ||
}, | ||
// WebGL1: Polyfills the WebGL2 Query API | ||
createQuery: function createQuery() { | ||
assert(false); | ||
}, | ||
deleteQuery: function deleteQuery() { | ||
assert(false); | ||
}, | ||
beginQuery: function beginQuery() { | ||
assert(false); | ||
}, | ||
endQuery: function endQuery() {}, | ||
getQuery: function getQuery(handle, pname) { | ||
return this.getQueryObject(handle, pname); | ||
}, | ||
// The WebGL1 extension uses getQueryObject rather then getQueryParameter | ||
getQueryParameter: function getQueryParameter(handle, pname) { | ||
return this.getQueryObject(handle, pname); | ||
}, | ||
getQueryObject: function getQueryObject() {} | ||
}), (0, _defineProperty2.default)(_WEBGL_CONTEXT_POLYFI, "OVERRIDES", { | ||
// Ensure readBuffer is a no-op | ||
readBuffer: function readBuffer(gl, originalFunc, attachment) { | ||
if (isWebGL2(gl)) { | ||
originalFunc(attachment); | ||
} else {// assert(attachment !== GL_COLOR_ATTACHMENT0 && attachment !== GL_FRONT); | ||
} | ||
}, | ||
// Override for getVertexAttrib that returns sane values for non-WebGL1 constants | ||
getVertexAttrib: function getVertexAttrib(gl, originalFunc, location, pname) { | ||
// const gl = this; // eslint-disable-line | ||
var _getExtensionData = getExtensionData(gl, ANGLE_instanced_arrays), | ||
webgl2 = _getExtensionData.webgl2, | ||
ext = _getExtensionData.ext; | ||
var result; | ||
switch (pname) { | ||
// WebGL1 attributes will never be integer | ||
case 35069: | ||
result = !webgl2 ? false : undefined; | ||
break; | ||
// if instancing is not available, return 0 meaning divisor has not been set | ||
case 35070: | ||
result = !webgl2 && !ext ? 0 : undefined; | ||
break; | ||
default: | ||
} | ||
return result !== undefined ? result : originalFunc(location, pname); | ||
}, | ||
// Handle transform feedback and uniform block queries in WebGL1 | ||
getProgramParameter: function getProgramParameter(gl, originalFunc, program, pname) { | ||
if (!isWebGL2(gl)) { | ||
switch (pname) { | ||
case 35967: | ||
return 35981; | ||
case 35971: | ||
return 0; | ||
case 35382: | ||
return 0; | ||
default: | ||
} | ||
} | ||
return originalFunc(program, pname); | ||
}, | ||
getInternalformatParameter: function getInternalformatParameter(gl, originalFunc, target, format, pname) { | ||
if (!isWebGL2(gl)) { | ||
switch (pname) { | ||
case 32937: | ||
return new Int32Array([0]); | ||
default: | ||
} | ||
} | ||
return gl.getInternalformatParameter(target, format, pname); | ||
}, | ||
getTexParameter: function getTexParameter(gl, originalFunc, target, pname) { | ||
switch (pname) { | ||
case 34046: | ||
var extensions = gl.luma.extensions; | ||
var ext = extensions[EXT_texture_filter_anisotropic]; | ||
pname = ext && ext.TEXTURE_MAX_ANISOTROPY_EXT || 34046; | ||
break; | ||
default: | ||
} | ||
return originalFunc(target, pname); | ||
}, | ||
getParameter: _polyfillGetParameter.getParameterPolyfill, | ||
hint: function hint(gl, originalFunc, pname, value) { | ||
// TODO - handle GL.FRAGMENT_SHADER_DERIVATIVE_HINT: | ||
// switch (pname) { | ||
// case GL.FRAGMENT_SHADER_DERIVATIVE_HINT: | ||
// } | ||
return originalFunc(pname, value); | ||
} | ||
}), _WEBGL_CONTEXT_POLYFI); | ||
function initializeExtensions(gl) { | ||
gl.luma.extensions = {}; // `getSupportedExtensions` can return null when context is lost. | ||
gl.luma.extensions = {}; | ||
var EXTENSIONS = gl.getSupportedExtensions() || []; | ||
@@ -217,11 +60,58 @@ var _iteratorNormalCompletion = true; | ||
} | ||
} // Polyfills a single WebGL extension into the `target` object | ||
} | ||
function installOverrides(gl, _ref) { | ||
var target = _ref.target, | ||
target2 = _ref.target2; | ||
Object.keys(_polyfillTable.WEBGL2_CONTEXT_OVERRIDES).forEach(function (key) { | ||
if (typeof _polyfillTable.WEBGL2_CONTEXT_OVERRIDES[key] === 'function') { | ||
var originalFunc = gl[key] ? gl[key].bind(gl) : function () {}; | ||
function polyfillExtension(gl, _ref) { | ||
var extension = _ref.extension, | ||
target = _ref.target, | ||
target2 = _ref.target2; | ||
var defaults = WEBGL_CONTEXT_POLYFILLS[extension]; | ||
assert(defaults); | ||
var polyfill = _polyfillTable.WEBGL2_CONTEXT_OVERRIDES[key].bind(null, gl, originalFunc); | ||
target[key] = polyfill; | ||
target2[key] = polyfill; | ||
} | ||
}); | ||
} | ||
function installPolyfills(gl, polyfills) { | ||
var _iteratorNormalCompletion2 = true; | ||
var _didIteratorError2 = false; | ||
var _iteratorError2 = undefined; | ||
try { | ||
for (var _iterator2 = Object.getOwnPropertyNames(polyfills)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { | ||
var extension = _step2.value; | ||
if (extension !== 'overrides') { | ||
polyfillExtension(gl, { | ||
extension: extension, | ||
target: gl.luma, | ||
target2: gl | ||
}); | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError2 = true; | ||
_iteratorError2 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion2 && _iterator2.return != null) { | ||
_iterator2.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError2) { | ||
throw _iteratorError2; | ||
} | ||
} | ||
} | ||
} | ||
function polyfillExtension(gl, _ref2) { | ||
var extension = _ref2.extension, | ||
target = _ref2.target, | ||
target2 = _ref2.target2; | ||
var defaults = _polyfillTable.WEBGL2_CONTEXT_POLYFILLS[extension]; | ||
(0, _assert.default)(defaults); | ||
var _defaults$meta = defaults.meta, | ||
@@ -232,10 +122,11 @@ meta = _defaults$meta === void 0 ? {} : _defaults$meta; | ||
var ext = gl.getExtension(extension); | ||
Object.keys(defaults).forEach(function (key) { | ||
var _arr = Object.keys(defaults); | ||
var _loop = function _loop() { | ||
var key = _arr[_i]; | ||
var extKey = "".concat(key).concat(suffix); | ||
var polyfill = null; | ||
if (key === 'meta') {// ignore | ||
} else if (typeof gl[key] === 'function') {// WebGL2 implementation is already | ||
} else if (ext && typeof ext[extKey] === 'function') { | ||
// pick extension implemenentation,if available | ||
if (key === 'meta') {} else if (typeof gl[key] === 'function') {} else if (ext && typeof ext[extKey] === 'function') { | ||
polyfill = function polyfill() { | ||
@@ -245,3 +136,2 @@ return ext[extKey].apply(ext, arguments); | ||
} else if (typeof defaults[key] === 'function') { | ||
// pick the mock implementation, if no implementation was detected | ||
polyfill = defaults[key].bind(target); | ||
@@ -254,51 +144,8 @@ } | ||
} | ||
}); | ||
} // Install simple overrides (mostly get* functions) | ||
}; | ||
function installOverrides(gl, _ref2) { | ||
var target = _ref2.target, | ||
target2 = _ref2.target2; | ||
var OVERRIDES = WEBGL_CONTEXT_POLYFILLS.OVERRIDES; | ||
Object.keys(OVERRIDES).forEach(function (key) { | ||
if (typeof OVERRIDES[key] === 'function') { | ||
// install an override, if no implementation was detected | ||
var originalFunc = gl[key] ? gl[key].bind(gl) : function () {}; | ||
var polyfill = OVERRIDES[key].bind(null, gl, originalFunc); | ||
target[key] = polyfill; | ||
target2[key] = polyfill; | ||
} | ||
}); | ||
} // Registers polyfill or mock functions for all known extensions | ||
function polyfillContext(gl) { | ||
// polyfillVertexArrayObject(WebGLRenderingContext, gl); | ||
gl.luma = gl.luma || {}; | ||
initializeExtensions(gl); | ||
if (!gl.luma.polyfilled) { | ||
Object.getOwnPropertyNames(WEBGL_CONTEXT_POLYFILLS).forEach(function (extension) { | ||
if (extension !== 'overrides') { | ||
polyfillExtension(gl, { | ||
extension: extension, | ||
target: gl.luma, | ||
target2: gl | ||
}); | ||
} | ||
}); | ||
installOverrides(gl, { | ||
target: gl.luma, | ||
target2: gl | ||
}); | ||
gl.luma.polyfilled = true; | ||
for (var _i = 0; _i < _arr.length; _i++) { | ||
_loop(); | ||
} | ||
return gl; | ||
} | ||
/* global window, global */ | ||
var global_ = typeof global !== 'undefined' ? global : window; | ||
global_.polyfillContext = polyfillContext; | ||
//# sourceMappingURL=polyfill-context.js.map |
@@ -1,4 +0,3 @@ | ||
// Installs polyfills to support a subset of WebGL2 APIs on WebGL1 contexts | ||
export { default as polyfillContext } from './polyfill-context'; | ||
export { default } from './polyfill-context'; | ||
//# sourceMappingURL=index.js.map |
@@ -1,203 +0,23 @@ | ||
// WebGL1/WebGL2 extension polyfill support | ||
// | ||
// Provides a function that creates polyfills for WebGL2 functions based | ||
// on available extensions and installs them on a supplied target (could be | ||
// the WebGLContext or its prototype, or a separate object). | ||
// | ||
// This is intended to be a stand-alone file with minimal dependencies, | ||
// easy to reuse or repurpose in other projects. | ||
import assert from './assert'; | ||
import { WEBGL2_CONTEXT_POLYFILLS, WEBGL2_CONTEXT_OVERRIDES } from './polyfill-table'; | ||
export default function polyfillContext(gl) { | ||
gl.luma = gl.luma || {}; | ||
initializeExtensions(gl); | ||
/* eslint-disable camelcase, brace-style */ | ||
import { getParameterPolyfill } from './polyfill-get-parameter'; | ||
if (!gl.luma.polyfilled) { | ||
installPolyfills(gl, WEBGL2_CONTEXT_POLYFILLS); | ||
installOverrides(gl, { | ||
target: gl.luma, | ||
target2: gl | ||
}); | ||
gl.luma.polyfilled = true; | ||
} | ||
function assert(condition, message) { | ||
if (!condition) { | ||
throw new Error(message || 'luma.gl: assertion failed.'); | ||
} | ||
return gl; | ||
} | ||
const global_ = typeof global !== 'undefined' ? global : window; | ||
global_.polyfillContext = polyfillContext; | ||
const OES_vertex_array_object = 'OES_vertex_array_object'; | ||
const ANGLE_instanced_arrays = 'ANGLE_instanced_arrays'; | ||
const WEBGL_draw_buffers = 'WEBGL_draw_buffers'; | ||
const EXT_disjoint_timer_query = 'EXT_disjoint_timer_query'; | ||
const EXT_texture_filter_anisotropic = 'EXT_texture_filter_anisotropic'; | ||
const ERR_VAO_NOT_SUPPORTED = 'VertexArray requires WebGL2 or OES_vertex_array_object extension'; // Return true if WebGL2 context | ||
function isWebGL2(gl) { | ||
return gl && 32874 === 32874; | ||
} // Return object with webgl2 flag and an extension | ||
function getExtensionData(gl, extension) { | ||
return { | ||
webgl2: isWebGL2(gl), | ||
ext: gl.getExtension(extension) | ||
}; | ||
} // function mapExtensionConstant(gl, constant) { | ||
// switch (constant) { | ||
// case ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES: return GL.FRAGMENT_SHADER_DERIVATIVE_HINT; | ||
// } | ||
// } | ||
const WEBGL_CONTEXT_POLYFILLS = { | ||
// POLYFILL TABLE | ||
[OES_vertex_array_object]: { | ||
meta: { | ||
suffix: 'OES' | ||
}, | ||
// NEW METHODS | ||
createVertexArray: () => { | ||
assert(false, ERR_VAO_NOT_SUPPORTED); | ||
}, | ||
deleteVertexArray: () => {}, | ||
bindVertexArray: () => {}, | ||
isVertexArray: () => false | ||
}, | ||
[ANGLE_instanced_arrays]: { | ||
meta: { | ||
suffix: 'ANGLE' // constants: { | ||
// VERTEX_ATTRIB_ARRAY_DIVISOR: 'VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE' | ||
// } | ||
}, | ||
vertexAttribDivisor(location, divisor) { | ||
// Accept divisor 0 even if instancing is not supported (0 = no instancing) | ||
assert(divisor === 0, 'WebGL instanced rendering not supported'); | ||
}, | ||
drawElementsInstanced: () => {}, | ||
drawArraysInstanced: () => {} | ||
}, | ||
[WEBGL_draw_buffers]: { | ||
meta: { | ||
suffix: 'WEBGL' | ||
}, | ||
drawBuffers: () => { | ||
assert(false); | ||
} | ||
}, | ||
[EXT_disjoint_timer_query]: { | ||
meta: { | ||
suffix: 'EXT' | ||
}, | ||
// WebGL1: Polyfills the WebGL2 Query API | ||
createQuery: () => { | ||
assert(false); | ||
}, | ||
deleteQuery: () => { | ||
assert(false); | ||
}, | ||
beginQuery: () => { | ||
assert(false); | ||
}, | ||
endQuery: () => {}, | ||
getQuery(handle, pname) { | ||
return this.getQueryObject(handle, pname); | ||
}, | ||
// The WebGL1 extension uses getQueryObject rather then getQueryParameter | ||
getQueryParameter(handle, pname) { | ||
return this.getQueryObject(handle, pname); | ||
}, | ||
getQueryObject: () => {} | ||
}, | ||
OVERRIDES: { | ||
// Ensure readBuffer is a no-op | ||
readBuffer: (gl, originalFunc, attachment) => { | ||
if (isWebGL2(gl)) { | ||
originalFunc(attachment); | ||
} else {// assert(attachment !== GL_COLOR_ATTACHMENT0 && attachment !== GL_FRONT); | ||
} | ||
}, | ||
// Override for getVertexAttrib that returns sane values for non-WebGL1 constants | ||
getVertexAttrib: (gl, originalFunc, location, pname) => { | ||
// const gl = this; // eslint-disable-line | ||
const _getExtensionData = getExtensionData(gl, ANGLE_instanced_arrays), | ||
webgl2 = _getExtensionData.webgl2, | ||
ext = _getExtensionData.ext; | ||
let result; | ||
switch (pname) { | ||
// WebGL1 attributes will never be integer | ||
case 35069: | ||
result = !webgl2 ? false : undefined; | ||
break; | ||
// if instancing is not available, return 0 meaning divisor has not been set | ||
case 35070: | ||
result = !webgl2 && !ext ? 0 : undefined; | ||
break; | ||
default: | ||
} | ||
return result !== undefined ? result : originalFunc(location, pname); | ||
}, | ||
// Handle transform feedback and uniform block queries in WebGL1 | ||
getProgramParameter: (gl, originalFunc, program, pname) => { | ||
if (!isWebGL2(gl)) { | ||
switch (pname) { | ||
case 35967: | ||
return 35981; | ||
case 35971: | ||
return 0; | ||
case 35382: | ||
return 0; | ||
default: | ||
} | ||
} | ||
return originalFunc(program, pname); | ||
}, | ||
getInternalformatParameter: (gl, originalFunc, target, format, pname) => { | ||
if (!isWebGL2(gl)) { | ||
switch (pname) { | ||
case 32937: | ||
return new Int32Array([0]); | ||
default: | ||
} | ||
} | ||
return gl.getInternalformatParameter(target, format, pname); | ||
}, | ||
getTexParameter(gl, originalFunc, target, pname) { | ||
switch (pname) { | ||
case 34046: | ||
const extensions = gl.luma.extensions; | ||
const ext = extensions[EXT_texture_filter_anisotropic]; | ||
pname = ext && ext.TEXTURE_MAX_ANISOTROPY_EXT || 34046; | ||
break; | ||
default: | ||
} | ||
return originalFunc(target, pname); | ||
}, | ||
getParameter: getParameterPolyfill, | ||
hint(gl, originalFunc, pname, value) { | ||
// TODO - handle GL.FRAGMENT_SHADER_DERIVATIVE_HINT: | ||
// switch (pname) { | ||
// case GL.FRAGMENT_SHADER_DERIVATIVE_HINT: | ||
// } | ||
return originalFunc(pname, value); | ||
} | ||
} | ||
}; | ||
function initializeExtensions(gl) { | ||
gl.luma.extensions = {}; // `getSupportedExtensions` can return null when context is lost. | ||
gl.luma.extensions = {}; | ||
const EXTENSIONS = gl.getSupportedExtensions() || []; | ||
@@ -208,5 +28,30 @@ | ||
} | ||
} // Polyfills a single WebGL extension into the `target` object | ||
} | ||
function installOverrides(gl, { | ||
target, | ||
target2 | ||
}) { | ||
Object.keys(WEBGL2_CONTEXT_OVERRIDES).forEach(key => { | ||
if (typeof WEBGL2_CONTEXT_OVERRIDES[key] === 'function') { | ||
const originalFunc = gl[key] ? gl[key].bind(gl) : () => {}; | ||
const polyfill = WEBGL2_CONTEXT_OVERRIDES[key].bind(null, gl, originalFunc); | ||
target[key] = polyfill; | ||
target2[key] = polyfill; | ||
} | ||
}); | ||
} | ||
function installPolyfills(gl, polyfills) { | ||
for (const extension of Object.getOwnPropertyNames(polyfills)) { | ||
if (extension !== 'overrides') { | ||
polyfillExtension(gl, { | ||
extension, | ||
target: gl.luma, | ||
target2: gl | ||
}); | ||
} | ||
} | ||
} | ||
function polyfillExtension(gl, { | ||
@@ -217,3 +62,3 @@ extension, | ||
}) { | ||
const defaults = WEBGL_CONTEXT_POLYFILLS[extension]; | ||
const defaults = WEBGL2_CONTEXT_POLYFILLS[extension]; | ||
assert(defaults); | ||
@@ -225,13 +70,10 @@ const _defaults$meta = defaults.meta, | ||
const ext = gl.getExtension(extension); | ||
Object.keys(defaults).forEach(key => { | ||
for (const key of Object.keys(defaults)) { | ||
const extKey = `${key}${suffix}`; | ||
let polyfill = null; | ||
if (key === 'meta') {// ignore | ||
} else if (typeof gl[key] === 'function') {// WebGL2 implementation is already | ||
} else if (ext && typeof ext[extKey] === 'function') { | ||
// pick extension implemenentation,if available | ||
if (key === 'meta') {} else if (typeof gl[key] === 'function') {} else if (ext && typeof ext[extKey] === 'function') { | ||
polyfill = (...args) => ext[extKey](...args); | ||
} else if (typeof defaults[key] === 'function') { | ||
// pick the mock implementation, if no implementation was detected | ||
polyfill = defaults[key].bind(target); | ||
@@ -244,51 +86,4 @@ } | ||
} | ||
}); | ||
} // Install simple overrides (mostly get* functions) | ||
function installOverrides(gl, { | ||
target, | ||
target2 | ||
}) { | ||
const OVERRIDES = WEBGL_CONTEXT_POLYFILLS.OVERRIDES; | ||
Object.keys(OVERRIDES).forEach(key => { | ||
if (typeof OVERRIDES[key] === 'function') { | ||
// install an override, if no implementation was detected | ||
const originalFunc = gl[key] ? gl[key].bind(gl) : () => {}; | ||
const polyfill = OVERRIDES[key].bind(null, gl, originalFunc); | ||
target[key] = polyfill; | ||
target2[key] = polyfill; | ||
} | ||
}); | ||
} // Registers polyfill or mock functions for all known extensions | ||
export default function polyfillContext(gl) { | ||
// polyfillVertexArrayObject(WebGLRenderingContext, gl); | ||
gl.luma = gl.luma || {}; | ||
initializeExtensions(gl); | ||
if (!gl.luma.polyfilled) { | ||
Object.getOwnPropertyNames(WEBGL_CONTEXT_POLYFILLS).forEach(extension => { | ||
if (extension !== 'overrides') { | ||
polyfillExtension(gl, { | ||
extension, | ||
target: gl.luma, | ||
target2: gl | ||
}); | ||
} | ||
}); | ||
installOverrides(gl, { | ||
target: gl.luma, | ||
target2: gl | ||
}); | ||
gl.luma.polyfilled = true; | ||
} | ||
return gl; | ||
} | ||
/* global window, global */ | ||
const global_ = typeof global !== 'undefined' ? global : window; | ||
global_.polyfillContext = polyfillContext; | ||
//# sourceMappingURL=polyfill-context.js.map |
@@ -1,4 +0,3 @@ | ||
// Installs polyfills to support a subset of WebGL2 APIs on WebGL1 contexts | ||
export { default as polyfillContext } from './polyfill-context'; | ||
export { default } from './polyfill-context'; | ||
//# sourceMappingURL=index.js.map |
@@ -1,193 +0,23 @@ | ||
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; | ||
import assert from './assert'; | ||
import { WEBGL2_CONTEXT_POLYFILLS, WEBGL2_CONTEXT_OVERRIDES } from './polyfill-table'; | ||
export default function polyfillContext(gl) { | ||
gl.luma = gl.luma || {}; | ||
initializeExtensions(gl); | ||
var _WEBGL_CONTEXT_POLYFI; | ||
if (!gl.luma.polyfilled) { | ||
installPolyfills(gl, WEBGL2_CONTEXT_POLYFILLS); | ||
installOverrides(gl, { | ||
target: gl.luma, | ||
target2: gl | ||
}); | ||
gl.luma.polyfilled = true; | ||
} | ||
// WebGL1/WebGL2 extension polyfill support | ||
// | ||
// Provides a function that creates polyfills for WebGL2 functions based | ||
// on available extensions and installs them on a supplied target (could be | ||
// the WebGLContext or its prototype, or a separate object). | ||
// | ||
// This is intended to be a stand-alone file with minimal dependencies, | ||
// easy to reuse or repurpose in other projects. | ||
/* eslint-disable camelcase, brace-style */ | ||
import { getParameterPolyfill } from './polyfill-get-parameter'; | ||
function assert(condition, message) { | ||
if (!condition) { | ||
throw new Error(message || 'luma.gl: assertion failed.'); | ||
} | ||
return gl; | ||
} | ||
var global_ = typeof global !== 'undefined' ? global : window; | ||
global_.polyfillContext = polyfillContext; | ||
var OES_vertex_array_object = 'OES_vertex_array_object'; | ||
var ANGLE_instanced_arrays = 'ANGLE_instanced_arrays'; | ||
var WEBGL_draw_buffers = 'WEBGL_draw_buffers'; | ||
var EXT_disjoint_timer_query = 'EXT_disjoint_timer_query'; | ||
var EXT_texture_filter_anisotropic = 'EXT_texture_filter_anisotropic'; | ||
var ERR_VAO_NOT_SUPPORTED = 'VertexArray requires WebGL2 or OES_vertex_array_object extension'; // Return true if WebGL2 context | ||
function isWebGL2(gl) { | ||
return gl && 32874 === 32874; | ||
} // Return object with webgl2 flag and an extension | ||
function getExtensionData(gl, extension) { | ||
return { | ||
webgl2: isWebGL2(gl), | ||
ext: gl.getExtension(extension) | ||
}; | ||
} // function mapExtensionConstant(gl, constant) { | ||
// switch (constant) { | ||
// case ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES: return GL.FRAGMENT_SHADER_DERIVATIVE_HINT; | ||
// } | ||
// } | ||
var WEBGL_CONTEXT_POLYFILLS = (_WEBGL_CONTEXT_POLYFI = {}, _defineProperty(_WEBGL_CONTEXT_POLYFI, OES_vertex_array_object, { | ||
meta: { | ||
suffix: 'OES' | ||
}, | ||
// NEW METHODS | ||
createVertexArray: function createVertexArray() { | ||
assert(false, ERR_VAO_NOT_SUPPORTED); | ||
}, | ||
deleteVertexArray: function deleteVertexArray() {}, | ||
bindVertexArray: function bindVertexArray() {}, | ||
isVertexArray: function isVertexArray() { | ||
return false; | ||
} | ||
}), _defineProperty(_WEBGL_CONTEXT_POLYFI, ANGLE_instanced_arrays, { | ||
meta: { | ||
suffix: 'ANGLE' // constants: { | ||
// VERTEX_ATTRIB_ARRAY_DIVISOR: 'VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE' | ||
// } | ||
}, | ||
vertexAttribDivisor: function vertexAttribDivisor(location, divisor) { | ||
// Accept divisor 0 even if instancing is not supported (0 = no instancing) | ||
assert(divisor === 0, 'WebGL instanced rendering not supported'); | ||
}, | ||
drawElementsInstanced: function drawElementsInstanced() {}, | ||
drawArraysInstanced: function drawArraysInstanced() {} | ||
}), _defineProperty(_WEBGL_CONTEXT_POLYFI, WEBGL_draw_buffers, { | ||
meta: { | ||
suffix: 'WEBGL' | ||
}, | ||
drawBuffers: function drawBuffers() { | ||
assert(false); | ||
} | ||
}), _defineProperty(_WEBGL_CONTEXT_POLYFI, EXT_disjoint_timer_query, { | ||
meta: { | ||
suffix: 'EXT' | ||
}, | ||
// WebGL1: Polyfills the WebGL2 Query API | ||
createQuery: function createQuery() { | ||
assert(false); | ||
}, | ||
deleteQuery: function deleteQuery() { | ||
assert(false); | ||
}, | ||
beginQuery: function beginQuery() { | ||
assert(false); | ||
}, | ||
endQuery: function endQuery() {}, | ||
getQuery: function getQuery(handle, pname) { | ||
return this.getQueryObject(handle, pname); | ||
}, | ||
// The WebGL1 extension uses getQueryObject rather then getQueryParameter | ||
getQueryParameter: function getQueryParameter(handle, pname) { | ||
return this.getQueryObject(handle, pname); | ||
}, | ||
getQueryObject: function getQueryObject() {} | ||
}), _defineProperty(_WEBGL_CONTEXT_POLYFI, "OVERRIDES", { | ||
// Ensure readBuffer is a no-op | ||
readBuffer: function readBuffer(gl, originalFunc, attachment) { | ||
if (isWebGL2(gl)) { | ||
originalFunc(attachment); | ||
} else {// assert(attachment !== GL_COLOR_ATTACHMENT0 && attachment !== GL_FRONT); | ||
} | ||
}, | ||
// Override for getVertexAttrib that returns sane values for non-WebGL1 constants | ||
getVertexAttrib: function getVertexAttrib(gl, originalFunc, location, pname) { | ||
// const gl = this; // eslint-disable-line | ||
var _getExtensionData = getExtensionData(gl, ANGLE_instanced_arrays), | ||
webgl2 = _getExtensionData.webgl2, | ||
ext = _getExtensionData.ext; | ||
var result; | ||
switch (pname) { | ||
// WebGL1 attributes will never be integer | ||
case 35069: | ||
result = !webgl2 ? false : undefined; | ||
break; | ||
// if instancing is not available, return 0 meaning divisor has not been set | ||
case 35070: | ||
result = !webgl2 && !ext ? 0 : undefined; | ||
break; | ||
default: | ||
} | ||
return result !== undefined ? result : originalFunc(location, pname); | ||
}, | ||
// Handle transform feedback and uniform block queries in WebGL1 | ||
getProgramParameter: function getProgramParameter(gl, originalFunc, program, pname) { | ||
if (!isWebGL2(gl)) { | ||
switch (pname) { | ||
case 35967: | ||
return 35981; | ||
case 35971: | ||
return 0; | ||
case 35382: | ||
return 0; | ||
default: | ||
} | ||
} | ||
return originalFunc(program, pname); | ||
}, | ||
getInternalformatParameter: function getInternalformatParameter(gl, originalFunc, target, format, pname) { | ||
if (!isWebGL2(gl)) { | ||
switch (pname) { | ||
case 32937: | ||
return new Int32Array([0]); | ||
default: | ||
} | ||
} | ||
return gl.getInternalformatParameter(target, format, pname); | ||
}, | ||
getTexParameter: function getTexParameter(gl, originalFunc, target, pname) { | ||
switch (pname) { | ||
case 34046: | ||
var extensions = gl.luma.extensions; | ||
var ext = extensions[EXT_texture_filter_anisotropic]; | ||
pname = ext && ext.TEXTURE_MAX_ANISOTROPY_EXT || 34046; | ||
break; | ||
default: | ||
} | ||
return originalFunc(target, pname); | ||
}, | ||
getParameter: getParameterPolyfill, | ||
hint: function hint(gl, originalFunc, pname, value) { | ||
// TODO - handle GL.FRAGMENT_SHADER_DERIVATIVE_HINT: | ||
// switch (pname) { | ||
// case GL.FRAGMENT_SHADER_DERIVATIVE_HINT: | ||
// } | ||
return originalFunc(pname, value); | ||
} | ||
}), _WEBGL_CONTEXT_POLYFI); | ||
function initializeExtensions(gl) { | ||
gl.luma.extensions = {}; // `getSupportedExtensions` can return null when context is lost. | ||
gl.luma.extensions = {}; | ||
var EXTENSIONS = gl.getSupportedExtensions() || []; | ||
@@ -217,10 +47,55 @@ var _iteratorNormalCompletion = true; | ||
} | ||
} // Polyfills a single WebGL extension into the `target` object | ||
} | ||
function installOverrides(gl, _ref) { | ||
var target = _ref.target, | ||
target2 = _ref.target2; | ||
Object.keys(WEBGL2_CONTEXT_OVERRIDES).forEach(function (key) { | ||
if (typeof WEBGL2_CONTEXT_OVERRIDES[key] === 'function') { | ||
var originalFunc = gl[key] ? gl[key].bind(gl) : function () {}; | ||
var polyfill = WEBGL2_CONTEXT_OVERRIDES[key].bind(null, gl, originalFunc); | ||
target[key] = polyfill; | ||
target2[key] = polyfill; | ||
} | ||
}); | ||
} | ||
function polyfillExtension(gl, _ref) { | ||
var extension = _ref.extension, | ||
target = _ref.target, | ||
target2 = _ref.target2; | ||
var defaults = WEBGL_CONTEXT_POLYFILLS[extension]; | ||
function installPolyfills(gl, polyfills) { | ||
var _iteratorNormalCompletion2 = true; | ||
var _didIteratorError2 = false; | ||
var _iteratorError2 = undefined; | ||
try { | ||
for (var _iterator2 = Object.getOwnPropertyNames(polyfills)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { | ||
var extension = _step2.value; | ||
if (extension !== 'overrides') { | ||
polyfillExtension(gl, { | ||
extension: extension, | ||
target: gl.luma, | ||
target2: gl | ||
}); | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError2 = true; | ||
_iteratorError2 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion2 && _iterator2.return != null) { | ||
_iterator2.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError2) { | ||
throw _iteratorError2; | ||
} | ||
} | ||
} | ||
} | ||
function polyfillExtension(gl, _ref2) { | ||
var extension = _ref2.extension, | ||
target = _ref2.target, | ||
target2 = _ref2.target2; | ||
var defaults = WEBGL2_CONTEXT_POLYFILLS[extension]; | ||
assert(defaults); | ||
@@ -232,10 +107,11 @@ var _defaults$meta = defaults.meta, | ||
var ext = gl.getExtension(extension); | ||
Object.keys(defaults).forEach(function (key) { | ||
var _arr = Object.keys(defaults); | ||
var _loop = function _loop() { | ||
var key = _arr[_i]; | ||
var extKey = "".concat(key).concat(suffix); | ||
var polyfill = null; | ||
if (key === 'meta') {// ignore | ||
} else if (typeof gl[key] === 'function') {// WebGL2 implementation is already | ||
} else if (ext && typeof ext[extKey] === 'function') { | ||
// pick extension implemenentation,if available | ||
if (key === 'meta') {} else if (typeof gl[key] === 'function') {} else if (ext && typeof ext[extKey] === 'function') { | ||
polyfill = function polyfill() { | ||
@@ -245,3 +121,2 @@ return ext[extKey].apply(ext, arguments); | ||
} else if (typeof defaults[key] === 'function') { | ||
// pick the mock implementation, if no implementation was detected | ||
polyfill = defaults[key].bind(target); | ||
@@ -254,50 +129,8 @@ } | ||
} | ||
}); | ||
} // Install simple overrides (mostly get* functions) | ||
}; | ||
function installOverrides(gl, _ref2) { | ||
var target = _ref2.target, | ||
target2 = _ref2.target2; | ||
var OVERRIDES = WEBGL_CONTEXT_POLYFILLS.OVERRIDES; | ||
Object.keys(OVERRIDES).forEach(function (key) { | ||
if (typeof OVERRIDES[key] === 'function') { | ||
// install an override, if no implementation was detected | ||
var originalFunc = gl[key] ? gl[key].bind(gl) : function () {}; | ||
var polyfill = OVERRIDES[key].bind(null, gl, originalFunc); | ||
target[key] = polyfill; | ||
target2[key] = polyfill; | ||
} | ||
}); | ||
} // Registers polyfill or mock functions for all known extensions | ||
export default function polyfillContext(gl) { | ||
// polyfillVertexArrayObject(WebGLRenderingContext, gl); | ||
gl.luma = gl.luma || {}; | ||
initializeExtensions(gl); | ||
if (!gl.luma.polyfilled) { | ||
Object.getOwnPropertyNames(WEBGL_CONTEXT_POLYFILLS).forEach(function (extension) { | ||
if (extension !== 'overrides') { | ||
polyfillExtension(gl, { | ||
extension: extension, | ||
target: gl.luma, | ||
target2: gl | ||
}); | ||
} | ||
}); | ||
installOverrides(gl, { | ||
target: gl.luma, | ||
target2: gl | ||
}); | ||
gl.luma.polyfilled = true; | ||
for (var _i = 0; _i < _arr.length; _i++) { | ||
_loop(); | ||
} | ||
return gl; | ||
} | ||
/* global window, global */ | ||
var global_ = typeof global !== 'undefined' ? global : window; | ||
global_.polyfillContext = polyfillContext; | ||
//# sourceMappingURL=polyfill-context.js.map |
{ | ||
"name": "@luma.gl/webgl2-polyfill", | ||
"version": "7.0.0-alpha.14", | ||
"version": "7.0.0-alpha.15", | ||
"description": "WebGL2 API Polyfills for WebGL1 WebGLRenderingContext", | ||
@@ -32,3 +32,3 @@ "license": "MIT", | ||
"@babel/runtime": "^7.0.0", | ||
"@luma.gl/constants": "^7.0.0-alpha.6" | ||
"@luma.gl/constants": "^7.0.0-alpha.15" | ||
}, | ||
@@ -35,0 +35,0 @@ "devDependencies": { |
# @luma.gl/webgl2-polyfill | ||
This moduls installs a partial set of polyfills for WebGL1 contexts, making them more API compatible with WebGL2. | ||
This module installs a partial set of polyfills for WebGL1 contexts, making them more API compatible with WebGL2. | ||
@@ -8,4 +8,5 @@ * It adds WebGL2 methods to the WebGL1 context, and simply forwards the calls to WebGL1 extensions. | ||
This way applications can work directly with the WebGL2 API even when using WebGL1 with extensions. It removes conditional code from applications and prepares application code bases for WebGL2. | ||
This way applications can use the WebGL2 API even when using WebGL1 with extensions. While you will still have to check that the extensions you need are available, using the WebGL2 API removes multiple code paths from your application and prepares your code base for WebGL2. | ||
## Usage | ||
@@ -25,4 +26,48 @@ | ||
## Functions | ||
### polyfillContext(gl : WebGLRenderingContext) : WebGLRenderingContext | ||
Installs WebGL2 polyfills on the supplied context. | ||
Returns: the supplied context, with additional methods added (unless it was already a `WebGL2RenderingContext` in which case those methods were already present). | ||
Note: Can be called multiple times and will only install the polyfills once. | ||
## Polyfill List | ||
After `polyfillContext` has been called on a `WebGLRenderingContext`, the following `WebGL2RenderingContext` methods will be available on the context: | ||
| Polyfilled Method | Uses Extension | Fallback if no extension | | ||
| --- | --- | --- | | ||
| `gl.createVertexArray()` | `OES_vertex_array_object` | throws error | | ||
| `gl.deleteVertexArray()` | | ignored | | ||
| `gl.bindVertexArray()` | | ignored | | ||
| `gl.isVertexArray()` | | ignored | | ||
| Polyfilled Method | Uses Extension | Fallback if no extension | | ||
| --- | --- | --- | | ||
| `gl.vertexAttribDivisor()` | `ANGLE_instanced_arrays` | throws error | | ||
| `gl.drawElementsInstanced()` | | ignored | | ||
| `gl.drawArraysInstanced()` | | ignored | | ||
| Polyfilled Method | Uses Extension | Fallback if no extension | | ||
| --- | --- | --- | | ||
| `gl.drawBuffers()` | `WEBGL_draw_buffers` | throws error | | ||
| Polyfilled Method | Uses Extension | Fallback if no extension | | ||
| --- | --- | --- | | ||
| `gl.createQuery()` | `EXT_disjoint_timer_query` | throws error | | ||
| `gl.deleteQuery()` | | ignored | | ||
| `gl.beginQuery()` | | ignored | | ||
| `gl.endQuery()` | | ignored | | ||
| `gl.getQuery()` | | ignored | | ||
| `gl.getQueryParameter()` | | ignored | | ||
## Remarks | ||
* This a helper module for [luma.gl](http://luma.gl), but is designed to be independently usable in other projects. | ||
* This module was originally created as a helper for [luma.gl](http://luma.gl), but is designed to be independently usable in other projects. It has no dependencies and makes no assumptions about other modules being available. |
@@ -11,170 +11,24 @@ // WebGL1/WebGL2 extension polyfill support | ||
/* eslint-disable camelcase, brace-style */ | ||
import GL from '@luma.gl/constants'; | ||
import {getParameterPolyfill} from './polyfill-get-parameter'; | ||
import assert from './assert'; | ||
function assert(condition, message) { | ||
if (!condition) { | ||
throw new Error(message || 'luma.gl: assertion failed.'); | ||
import {WEBGL2_CONTEXT_POLYFILLS, WEBGL2_CONTEXT_OVERRIDES} from './polyfill-table'; | ||
// Registers extensions, polyfills or mock functions for extensions in the polyfills list | ||
// TODO - remove use of name `luma`. | ||
export default function polyfillContext(gl) { | ||
gl.luma = gl.luma || {}; | ||
initializeExtensions(gl); | ||
if (!gl.luma.polyfilled) { | ||
installPolyfills(gl, WEBGL2_CONTEXT_POLYFILLS); | ||
installOverrides(gl, {target: gl.luma, target2: gl}); | ||
gl.luma.polyfilled = true; | ||
} | ||
return gl; | ||
} | ||
const OES_vertex_array_object = 'OES_vertex_array_object'; | ||
const ANGLE_instanced_arrays = 'ANGLE_instanced_arrays'; | ||
const WEBGL_draw_buffers = 'WEBGL_draw_buffers'; | ||
const EXT_disjoint_timer_query = 'EXT_disjoint_timer_query'; | ||
const EXT_texture_filter_anisotropic = 'EXT_texture_filter_anisotropic'; | ||
// TODO - is this still required? | ||
/* global window, global */ | ||
const global_ = typeof global !== 'undefined' ? global : window; | ||
global_.polyfillContext = polyfillContext; | ||
const ERR_VAO_NOT_SUPPORTED = 'VertexArray requires WebGL2 or OES_vertex_array_object extension'; | ||
// Return true if WebGL2 context | ||
function isWebGL2(gl) { | ||
return gl && gl.TEXTURE_BINDING_3D === GL.TEXTURE_BINDING_3D; | ||
} | ||
// Return object with webgl2 flag and an extension | ||
function getExtensionData(gl, extension) { | ||
return { | ||
webgl2: isWebGL2(gl), | ||
ext: gl.getExtension(extension) | ||
}; | ||
} | ||
// function mapExtensionConstant(gl, constant) { | ||
// switch (constant) { | ||
// case ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES: return GL.FRAGMENT_SHADER_DERIVATIVE_HINT; | ||
// } | ||
// } | ||
const WEBGL_CONTEXT_POLYFILLS = { | ||
// POLYFILL TABLE | ||
[OES_vertex_array_object]: { | ||
meta: {suffix: 'OES'}, | ||
// NEW METHODS | ||
createVertexArray: () => { | ||
assert(false, ERR_VAO_NOT_SUPPORTED); | ||
}, | ||
deleteVertexArray: () => {}, | ||
bindVertexArray: () => {}, | ||
isVertexArray: () => false | ||
}, | ||
[ANGLE_instanced_arrays]: { | ||
meta: { | ||
suffix: 'ANGLE' | ||
// constants: { | ||
// VERTEX_ATTRIB_ARRAY_DIVISOR: 'VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE' | ||
// } | ||
}, | ||
vertexAttribDivisor(location, divisor) { | ||
// Accept divisor 0 even if instancing is not supported (0 = no instancing) | ||
assert(divisor === 0, 'WebGL instanced rendering not supported'); | ||
}, | ||
drawElementsInstanced: () => {}, | ||
drawArraysInstanced: () => {} | ||
}, | ||
[WEBGL_draw_buffers]: { | ||
meta: { | ||
suffix: 'WEBGL' | ||
}, | ||
drawBuffers: () => { | ||
assert(false); | ||
} | ||
}, | ||
[EXT_disjoint_timer_query]: { | ||
meta: {suffix: 'EXT'}, | ||
// WebGL1: Polyfills the WebGL2 Query API | ||
createQuery: () => { | ||
assert(false); | ||
}, | ||
deleteQuery: () => { | ||
assert(false); | ||
}, | ||
beginQuery: () => { | ||
assert(false); | ||
}, | ||
endQuery: () => {}, | ||
getQuery(handle, pname) { | ||
return this.getQueryObject(handle, pname); | ||
}, | ||
// The WebGL1 extension uses getQueryObject rather then getQueryParameter | ||
getQueryParameter(handle, pname) { | ||
return this.getQueryObject(handle, pname); | ||
}, | ||
getQueryObject: () => {} | ||
}, | ||
OVERRIDES: { | ||
// Ensure readBuffer is a no-op | ||
readBuffer: (gl, originalFunc, attachment) => { | ||
if (isWebGL2(gl)) { | ||
originalFunc(attachment); | ||
} else { | ||
// assert(attachment !== GL_COLOR_ATTACHMENT0 && attachment !== GL_FRONT); | ||
} | ||
}, | ||
// Override for getVertexAttrib that returns sane values for non-WebGL1 constants | ||
getVertexAttrib: (gl, originalFunc, location, pname) => { | ||
// const gl = this; // eslint-disable-line | ||
const {webgl2, ext} = getExtensionData(gl, ANGLE_instanced_arrays); | ||
let result; | ||
switch (pname) { | ||
// WebGL1 attributes will never be integer | ||
case GL.VERTEX_ATTRIB_ARRAY_INTEGER: | ||
result = !webgl2 ? false : undefined; | ||
break; | ||
// if instancing is not available, return 0 meaning divisor has not been set | ||
case GL.VERTEX_ATTRIB_ARRAY_DIVISOR: | ||
result = !webgl2 && !ext ? 0 : undefined; | ||
break; | ||
default: | ||
} | ||
return result !== undefined ? result : originalFunc(location, pname); | ||
}, | ||
// Handle transform feedback and uniform block queries in WebGL1 | ||
getProgramParameter: (gl, originalFunc, program, pname) => { | ||
if (!isWebGL2(gl)) { | ||
switch (pname) { | ||
case GL.TRANSFORM_FEEDBACK_BUFFER_MODE: | ||
return GL.SEPARATE_ATTRIBS; | ||
case GL.TRANSFORM_FEEDBACK_VARYINGS: | ||
return 0; | ||
case GL.ACTIVE_UNIFORM_BLOCKS: | ||
return 0; | ||
default: | ||
} | ||
} | ||
return originalFunc(program, pname); | ||
}, | ||
getInternalformatParameter: (gl, originalFunc, target, format, pname) => { | ||
if (!isWebGL2(gl)) { | ||
switch (pname) { | ||
case GL.SAMPLES: | ||
return new Int32Array([0]); | ||
default: | ||
} | ||
} | ||
return gl.getInternalformatParameter(target, format, pname); | ||
}, | ||
getTexParameter(gl, originalFunc, target, pname) { | ||
switch (pname) { | ||
case GL.TEXTURE_MAX_ANISOTROPY_EXT: | ||
const {extensions} = gl.luma; | ||
const ext = extensions[EXT_texture_filter_anisotropic]; | ||
pname = (ext && ext.TEXTURE_MAX_ANISOTROPY_EXT) || GL.TEXTURE_MAX_ANISOTROPY_EXT; | ||
break; | ||
default: | ||
} | ||
return originalFunc(target, pname); | ||
}, | ||
getParameter: getParameterPolyfill, | ||
hint(gl, originalFunc, pname, value) { | ||
// TODO - handle GL.FRAGMENT_SHADER_DERIVATIVE_HINT: | ||
// switch (pname) { | ||
// case GL.FRAGMENT_SHADER_DERIVATIVE_HINT: | ||
// } | ||
return originalFunc(pname, value); | ||
} | ||
} | ||
}; | ||
function initializeExtensions(gl) { | ||
@@ -189,5 +43,26 @@ gl.luma.extensions = {}; | ||
// Install simple overrides (mostly get* functions) | ||
function installOverrides(gl, {target, target2}) { | ||
Object.keys(WEBGL2_CONTEXT_OVERRIDES).forEach(key => { | ||
if (typeof WEBGL2_CONTEXT_OVERRIDES[key] === 'function') { | ||
// install an override, if no implementation was detected | ||
const originalFunc = gl[key] ? gl[key].bind(gl) : () => {}; | ||
const polyfill = WEBGL2_CONTEXT_OVERRIDES[key].bind(null, gl, originalFunc); | ||
target[key] = polyfill; | ||
target2[key] = polyfill; | ||
} | ||
}); | ||
} | ||
function installPolyfills(gl, polyfills) { | ||
for (const extension of Object.getOwnPropertyNames(polyfills)) { | ||
if (extension !== 'overrides') { | ||
polyfillExtension(gl, {extension, target: gl.luma, target2: gl}); | ||
} | ||
} | ||
} | ||
// Polyfills a single WebGL extension into the `target` object | ||
function polyfillExtension(gl, {extension, target, target2}) { | ||
const defaults = WEBGL_CONTEXT_POLYFILLS[extension]; | ||
const defaults = WEBGL2_CONTEXT_POLYFILLS[extension]; | ||
assert(defaults); | ||
@@ -200,3 +75,3 @@ | ||
Object.keys(defaults).forEach(key => { | ||
for (const key of Object.keys(defaults)) { | ||
const extKey = `${key}${suffix}`; | ||
@@ -221,38 +96,3 @@ | ||
} | ||
}); | ||
} | ||
// Install simple overrides (mostly get* functions) | ||
function installOverrides(gl, {target, target2}) { | ||
const {OVERRIDES} = WEBGL_CONTEXT_POLYFILLS; | ||
Object.keys(OVERRIDES).forEach(key => { | ||
if (typeof OVERRIDES[key] === 'function') { | ||
// install an override, if no implementation was detected | ||
const originalFunc = gl[key] ? gl[key].bind(gl) : () => {}; | ||
const polyfill = OVERRIDES[key].bind(null, gl, originalFunc); | ||
target[key] = polyfill; | ||
target2[key] = polyfill; | ||
} | ||
}); | ||
} | ||
// Registers polyfill or mock functions for all known extensions | ||
export default function polyfillContext(gl) { | ||
// polyfillVertexArrayObject(WebGLRenderingContext, gl); | ||
gl.luma = gl.luma || {}; | ||
initializeExtensions(gl); | ||
if (!gl.luma.polyfilled) { | ||
Object.getOwnPropertyNames(WEBGL_CONTEXT_POLYFILLS).forEach(extension => { | ||
if (extension !== 'overrides') { | ||
polyfillExtension(gl, {extension, target: gl.luma, target2: gl}); | ||
} | ||
}); | ||
installOverrides(gl, {target: gl.luma, target2: gl}); | ||
gl.luma.polyfilled = true; | ||
} | ||
return gl; | ||
} | ||
/* global window, global */ | ||
const global_ = typeof global !== 'undefined' ? global : window; | ||
global_.polyfillContext = polyfillContext; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
37
72
137919
1336
2