@polygonjs/plugin-mapbox
Version:
Mapbox plugin for the 3D engine https://polygonjs.com
1,832 lines (1,730 loc) • 123 kB
JavaScript
/* webgl-lint@1.8.0, license MIT */
(function (factory) {
typeof define === 'function' && define.amd ? define(factory) : factory();
})(function () {
'use strict';
function isBuiltIn(name) {
return name.startsWith('gl_') || name.startsWith('webgl_');
}
function isWebGL2(gl) {
// a proxy for if this is webgl
return !!gl.texImage3D;
}
function isTypedArray(v) {
return v && v.buffer && v.buffer instanceof ArrayBuffer;
}
function isArrayThatCanHaveBadValues(v) {
return Array.isArray(v) || v instanceof Float32Array || v instanceof Float64Array;
}
function quotedStringOrEmpty(s) {
return s ? `"${s}"` : '';
}
/**
* Map of names to numbers.
* @type {Object}
*/
const enumStringToValue = {};
function enumArrayToString(gl, enums) {
const enumStrings = [];
if (enums.length) {
for (let i = 0; i < enums.length; ++i) {
enums.push(glEnumToString(enums[i])); // eslint-disable-line
}
return '[' + enumStrings.join(', ') + ']';
}
return enumStrings.toString();
}
function makeBitFieldToStringFunc(enums) {
return function (gl, value) {
let orResult = 0;
const orEnums = [];
for (let i = 0; i < enums.length; ++i) {
const enumValue = enumStringToValue[enums[i]];
if ((value & enumValue) !== 0) {
orResult |= enumValue;
orEnums.push(glEnumToString(enumValue)); // eslint-disable-line
}
}
if (orResult === value) {
return orEnums.join(' | ');
} else {
return glEnumToString(value); // eslint-disable-line
}
};
}
/** @type Map<int, Set<string>> */
const enumToStringsMap = new Map();
function addEnumsFromAPI(api) {
for (const key in api) {
const value = api[key];
if (typeof value === 'number') {
if (!enumToStringsMap.has(value)) {
enumToStringsMap.set(value, new Set());
}
enumToStringsMap.get(value).add(key);
}
}
}
/**
* Gets an string version of an WebGL enum.
*
* Example:
* var str = WebGLDebugUtil.glEnumToString(ctx.getError());
*
* @param {number} value Value to return an enum for
* @return {string} The string version of the enum.
*/
function glEnumToString(value) {
const matches = enumToStringsMap.get(value);
return matches
? [...matches.keys()].map((v) => `${v}`).join(' | ')
: `/*UNKNOWN WebGL ENUM*/ ${typeof value === 'number' ? `0x${value.toString(16)}` : value}`;
}
// ---------------------------------
const FLOAT = 0x1406;
const FLOAT_VEC2 = 0x8b50;
const FLOAT_VEC3 = 0x8b51;
const FLOAT_VEC4 = 0x8b52;
const INT = 0x1404;
const INT_VEC2 = 0x8b53;
const INT_VEC3 = 0x8b54;
const INT_VEC4 = 0x8b55;
const BOOL = 0x8b56;
const BOOL_VEC2 = 0x8b57;
const BOOL_VEC3 = 0x8b58;
const BOOL_VEC4 = 0x8b59;
const FLOAT_MAT2 = 0x8b5a;
const FLOAT_MAT3 = 0x8b5b;
const FLOAT_MAT4 = 0x8b5c;
const SAMPLER_2D = 0x8b5e;
const SAMPLER_CUBE = 0x8b60;
const SAMPLER_3D = 0x8b5f;
const SAMPLER_2D_SHADOW = 0x8b62;
const FLOAT_MAT2x3 = 0x8b65;
const FLOAT_MAT2x4 = 0x8b66;
const FLOAT_MAT3x2 = 0x8b67;
const FLOAT_MAT3x4 = 0x8b68;
const FLOAT_MAT4x2 = 0x8b69;
const FLOAT_MAT4x3 = 0x8b6a;
const SAMPLER_2D_ARRAY = 0x8dc1;
const SAMPLER_2D_ARRAY_SHADOW = 0x8dc4;
const SAMPLER_CUBE_SHADOW = 0x8dc5;
const UNSIGNED_INT = 0x1405;
const UNSIGNED_INT_VEC2 = 0x8dc6;
const UNSIGNED_INT_VEC3 = 0x8dc7;
const UNSIGNED_INT_VEC4 = 0x8dc8;
const INT_SAMPLER_2D = 0x8dca;
const INT_SAMPLER_3D = 0x8dcb;
const INT_SAMPLER_CUBE = 0x8dcc;
const INT_SAMPLER_2D_ARRAY = 0x8dcf;
const UNSIGNED_INT_SAMPLER_2D = 0x8dd2;
const UNSIGNED_INT_SAMPLER_3D = 0x8dd3;
const UNSIGNED_INT_SAMPLER_CUBE = 0x8dd4;
const UNSIGNED_INT_SAMPLER_2D_ARRAY = 0x8dd7;
const uniformTypeMap = new Map([
[FLOAT, {size: 1, name: 'float'}],
[FLOAT_VEC2, {size: 2, name: 'vec2'}],
[FLOAT_VEC3, {size: 3, name: 'vec3'}],
[FLOAT_VEC4, {size: 4, name: 'vec4'}],
[INT, {size: 1, name: 'int'}],
[INT_VEC2, {size: 2, name: 'ivec2'}],
[INT_VEC3, {size: 3, name: 'ivec3'}],
[INT_VEC4, {size: 4, name: 'ivec4'}],
[UNSIGNED_INT, {size: 1, name: 'uint'}],
[UNSIGNED_INT_VEC2, {size: 2, name: 'uvec2'}],
[UNSIGNED_INT_VEC3, {size: 3, name: 'uvec3'}],
[UNSIGNED_INT_VEC4, {size: 4, name: 'uvec4'}],
[BOOL, {size: 1, name: 'bool'}],
[BOOL_VEC2, {size: 2, name: 'bvec2'}],
[BOOL_VEC3, {size: 3, name: 'bvec3'}],
[BOOL_VEC4, {size: 4, name: 'bvec4'}],
[FLOAT_MAT2, {size: 4, name: 'mat2'}],
[FLOAT_MAT3, {size: 9, name: 'mat3'}],
[FLOAT_MAT4, {size: 16, name: 'mat4'}],
[FLOAT_MAT2x3, {size: 6, name: 'mat2x3'}],
[FLOAT_MAT2x4, {size: 8, name: 'mat2x4'}],
[FLOAT_MAT3x2, {size: 6, name: 'mat3x2'}],
[FLOAT_MAT3x4, {size: 12, name: 'mat3x4'}],
[FLOAT_MAT4x2, {size: 8, name: 'mat4x2'}],
[FLOAT_MAT4x3, {size: 12, name: 'mat4x3'}],
[SAMPLER_2D, {size: 1, name: 'sampler2D'}],
[SAMPLER_CUBE, {size: 1, name: 'samplerCube'}],
[SAMPLER_3D, {size: 1, name: 'sampler3D'}],
[SAMPLER_2D_SHADOW, {size: 1, name: 'sampler2DShadow'}],
[SAMPLER_2D_ARRAY, {size: 1, name: 'sampler2DArray'}],
[SAMPLER_2D_ARRAY_SHADOW, {size: 1, name: 'sampler2DArrayShadow'}],
[SAMPLER_CUBE_SHADOW, {size: 1, name: 'samplerCubeShadow'}],
[INT_SAMPLER_2D, {size: 1, name: 'isampler2D'}],
[INT_SAMPLER_3D, {size: 1, name: 'isampler3D'}],
[INT_SAMPLER_CUBE, {size: 1, name: 'isamplerCube'}],
[INT_SAMPLER_2D_ARRAY, {size: 1, name: 'isampler2DArray'}],
[UNSIGNED_INT_SAMPLER_2D, {size: 1, name: 'usampler2D'}],
[UNSIGNED_INT_SAMPLER_3D, {size: 1, name: 'usampler3D'}],
[UNSIGNED_INT_SAMPLER_CUBE, {size: 1, name: 'usamplerCube'}],
[UNSIGNED_INT_SAMPLER_2D_ARRAY, {size: 1, name: 'usampler2DArray'}],
]);
function getUniformTypeInfo(type) {
return uniformTypeMap.get(type);
}
// ---------------------------------
const TEXTURE_BINDING_2D = 0x8069;
const TEXTURE_BINDING_CUBE_MAP = 0x8514;
const TEXTURE_BINDING_3D = 0x806a;
const TEXTURE_BINDING_2D_ARRAY = 0x8c1d;
const ARRAY_BUFFER = 0x8892;
const ELEMENT_ARRAY_BUFFER = 0x8893;
const ARRAY_BUFFER_BINDING = 0x8894;
const ELEMENT_ARRAY_BUFFER_BINDING = 0x8895;
const TEXTURE_2D = 0x0de1;
const TEXTURE_3D = 0x806f;
const TEXTURE_2D_ARRAY = 0x8c1a;
const TEXTURE_CUBE_MAP = 0x8513;
const FRAMEBUFFER = 0x8d40;
const RENDERBUFFER = 0x8d41;
const FRAMEBUFFER_BINDING = 0x8ca6;
const RENDERBUFFER_BINDING = 0x8ca7;
const TRANSFORM_FEEDBACK_BUFFER = 0x8c8e;
const TRANSFORM_FEEDBACK_BUFFER_BINDING = 0x8c8f;
const DRAW_FRAMEBUFFER = 0x8ca9;
const READ_FRAMEBUFFER = 0x8ca8;
const READ_FRAMEBUFFER_BINDING = 0x8caa;
const UNIFORM_BUFFER = 0x8a11;
const UNIFORM_BUFFER_BINDING = 0x8a28;
const TRANSFORM_FEEDBACK = 0x8e22;
const TRANSFORM_FEEDBACK_BINDING = 0x8e25;
const bindPointMap = new Map([
[ARRAY_BUFFER, ARRAY_BUFFER_BINDING],
[ELEMENT_ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER_BINDING],
[TEXTURE_2D, TEXTURE_BINDING_2D],
[TEXTURE_CUBE_MAP, TEXTURE_BINDING_CUBE_MAP],
[TEXTURE_3D, TEXTURE_BINDING_3D],
[TEXTURE_2D_ARRAY, TEXTURE_BINDING_2D_ARRAY],
[RENDERBUFFER, RENDERBUFFER_BINDING],
[FRAMEBUFFER, FRAMEBUFFER_BINDING],
[DRAW_FRAMEBUFFER, FRAMEBUFFER_BINDING],
[READ_FRAMEBUFFER, READ_FRAMEBUFFER_BINDING],
[UNIFORM_BUFFER, UNIFORM_BUFFER_BINDING],
[TRANSFORM_FEEDBACK_BUFFER, TRANSFORM_FEEDBACK_BUFFER_BINDING],
[TRANSFORM_FEEDBACK, TRANSFORM_FEEDBACK_BINDING],
]);
function getBindingQueryEnumForBindPoint(bindPoint) {
return bindPointMap.get(bindPoint);
}
const BYTE = 0x1400;
const SHORT = 0x1402;
const UNSIGNED_BYTE = 0x1401;
const UNSIGNED_SHORT = 0x1403;
const glTypeToSizeMap = new Map([
[BOOL, 1],
[BYTE, 1],
[UNSIGNED_BYTE, 1],
[SHORT, 2],
[UNSIGNED_SHORT, 2],
[INT, 4],
[UNSIGNED_INT, 4],
[FLOAT, 4],
]);
function getBytesPerValueForGLType(type) {
return glTypeToSizeMap.get(type) || 0;
}
const glTypeToTypedArrayMap = new Map([
[UNSIGNED_BYTE, Uint8Array],
[UNSIGNED_SHORT, Uint16Array],
[UNSIGNED_INT, Uint32Array],
]);
function glTypeToTypedArray(type) {
return glTypeToTypedArrayMap.get(type);
}
const drawFuncsToArgs = {
drawArrays(primType, startOffset, vertCount) {
return {startOffset, vertCount, instances: 1};
},
drawElements(primType, vertCount, indexType, startOffset) {
return {startOffset, vertCount, instances: 1, indexType};
},
drawArraysInstanced(primType, startOffset, vertCount, instances) {
return {startOffset, vertCount, instances};
},
drawElementsInstanced(primType, vertCount, indexType, startOffset, instances) {
return {startOffset, vertCount, instances, indexType};
},
drawArraysInstancedANGLE(primType, startOffset, vertCount, instances) {
return {startOffset, vertCount, instances};
},
drawElementsInstancedANGLE(primType, vertCount, indexType, startOffset, instances) {
return {startOffset, vertCount, instances, indexType};
},
drawRangeElements(primType, start, end, vertCount, indexType, startOffset) {
return {startOffset, vertCount, instances: 1, indexType};
},
};
function getDrawFunctionArgs(funcName, args) {
return drawFuncsToArgs[funcName](...args);
}
function isDrawFunction(funcName) {
return !!drawFuncsToArgs[funcName];
}
const attrTypeMap = new Map([
[FLOAT, {size: 4}],
[FLOAT_VEC2, {size: 8}],
[FLOAT_VEC3, {size: 12}],
[FLOAT_VEC4, {size: 16}],
[INT, {size: 4}],
[INT_VEC2, {size: 8}],
[INT_VEC3, {size: 12}],
[INT_VEC4, {size: 16}],
[UNSIGNED_INT, {size: 4}],
[UNSIGNED_INT_VEC2, {size: 8}],
[UNSIGNED_INT_VEC3, {size: 12}],
[UNSIGNED_INT_VEC4, {size: 16}],
[BOOL, {size: 4}],
[BOOL_VEC2, {size: 8}],
[BOOL_VEC3, {size: 12}],
[BOOL_VEC4, {size: 16}],
[FLOAT_MAT2, {size: 4, count: 2}],
[FLOAT_MAT3, {size: 9, count: 3}],
[FLOAT_MAT4, {size: 16, count: 4}],
]);
function getAttributeTypeInfo(type) {
return attrTypeMap.get(type);
}
const VERTEX_ATTRIB_ARRAY_DIVISOR = 0x88fe;
function computeLastUseIndexForDrawArrays(startOffset, vertCount /*, instances, errors*/) {
return startOffset + vertCount - 1;
}
function getLastUsedIndexForDrawElements(
gl,
funcName,
startOffset,
vertCount,
instances,
indexType,
getWebGLObjectString,
getIndicesForBuffer,
errors
) {
const elementBuffer = gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING);
if (!elementBuffer) {
errors.push('No ELEMENT_ARRAY_BUFFER bound');
return undefined;
}
const bytesPerIndex = getBytesPerValueForGLType(indexType);
const bufferSize = gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_SIZE);
const sizeNeeded = startOffset + vertCount * bytesPerIndex;
if (sizeNeeded > bufferSize) {
errors.push(`offset: ${startOffset} and count: ${vertCount} with index type: ${glEnumToString(
indexType
)} passed to ${funcName} are out of range for current ELEMENT_ARRAY_BUFFER.
Those parameters require ${sizeNeeded} bytes but the current ELEMENT_ARRAY_BUFFER ${getWebGLObjectString(
elementBuffer
)} only has ${bufferSize} bytes`);
return undefined;
}
const buffer = getIndicesForBuffer(elementBuffer);
const Type = glTypeToTypedArray(indexType);
const view = new Type(buffer, startOffset);
let maxIndex = view[0];
for (let i = 1; i < vertCount; ++i) {
maxIndex = Math.max(maxIndex, view[i]);
}
return maxIndex;
}
function checkAttributesForBufferOverflow(gl, funcName, args, getWebGLObjectString, getIndicesForBuffer) {
const {vertCount, startOffset, indexType, instances} = getDrawFunctionArgs(funcName, args);
if (vertCount <= 0 || instances <= 0) {
return [];
}
const program = gl.getParameter(gl.CURRENT_PROGRAM);
const errors = [];
const nonInstancedLastIndex = indexType
? getLastUsedIndexForDrawElements(
gl,
funcName,
startOffset,
vertCount,
instances,
indexType,
getWebGLObjectString,
getIndicesForBuffer,
errors
)
: computeLastUseIndexForDrawArrays(startOffset, vertCount);
if (errors.length) {
return errors;
}
const hasDivisor = isWebGL2(gl) || gl.getExtension('ANGLE_instanced_arrays');
// get the attributes used by the current program
const numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
const oldArrayBuffer = gl.getParameter(gl.ARRAY_BUFFER_BINDING);
for (let ii = 0; ii < numAttributes; ++ii) {
const {name, type} = gl.getActiveAttrib(program, ii);
if (isBuiltIn(name)) {
continue;
}
const index = gl.getAttribLocation(program, name);
const {count} = {count: 1, ...getAttributeTypeInfo(type)};
for (let jj = 0; jj < count; ++jj) {
const ndx = index + jj;
const enabled = gl.getVertexAttrib(ndx, gl.VERTEX_ATTRIB_ARRAY_ENABLED);
if (!enabled) {
continue;
}
const buffer = gl.getVertexAttrib(ndx, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
if (!buffer) {
errors.push(`no buffer bound to attribute (${name}) location: ${index}`);
continue;
}
const numComponents = gl.getVertexAttrib(ndx, gl.VERTEX_ATTRIB_ARRAY_SIZE);
const type = gl.getVertexAttrib(ndx, gl.VERTEX_ATTRIB_ARRAY_TYPE);
const bytesPerElement = getBytesPerValueForGLType(type) * numComponents;
const offset = gl.getVertexAttribOffset(ndx, gl.VERTEX_ATTRIB_ARRAY_POINTER);
const specifiedStride = gl.getVertexAttrib(ndx, gl.VERTEX_ATTRIB_ARRAY_STRIDE);
const stride = specifiedStride ? specifiedStride : bytesPerElement;
const divisor = hasDivisor ? gl.getVertexAttrib(ndx, VERTEX_ATTRIB_ARRAY_DIVISOR) : 0;
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
const bufferSize = gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE);
const effectiveLastIndex =
divisor > 0 ? (((instances + divisor - 1) / divisor) | 0) - 1 : nonInstancedLastIndex;
const sizeNeeded = offset + effectiveLastIndex * stride + bytesPerElement;
if (sizeNeeded > bufferSize) {
errors.push(`${getWebGLObjectString(
buffer
)} assigned to attribute ${ndx} used as attribute '${name}' in current program is too small for draw parameters.
index of highest vertex accessed: ${effectiveLastIndex}
attribute size: ${numComponents}, type: ${glEnumToString(
type
)}, stride: ${specifiedStride}, offset: ${offset}, divisor: ${divisor}
needs ${sizeNeeded} bytes for draw but buffer is only ${bufferSize} bytes`);
}
}
}
gl.bindBuffer(gl.ARRAY_BUFFER, oldArrayBuffer);
return errors;
}
const SAMPLER_2D$1 = 0x8b5e;
const SAMPLER_CUBE$1 = 0x8b60;
const SAMPLER_3D$1 = 0x8b5f;
const SAMPLER_2D_SHADOW$1 = 0x8b62;
const SAMPLER_2D_ARRAY$1 = 0x8dc1;
const SAMPLER_2D_ARRAY_SHADOW$1 = 0x8dc4;
const SAMPLER_CUBE_SHADOW$1 = 0x8dc5;
const INT_SAMPLER_2D$1 = 0x8dca;
const INT_SAMPLER_3D$1 = 0x8dcb;
const INT_SAMPLER_CUBE$1 = 0x8dcc;
const INT_SAMPLER_2D_ARRAY$1 = 0x8dcf;
const UNSIGNED_INT_SAMPLER_2D$1 = 0x8dd2;
const UNSIGNED_INT_SAMPLER_3D$1 = 0x8dd3;
const UNSIGNED_INT_SAMPLER_CUBE$1 = 0x8dd4;
const UNSIGNED_INT_SAMPLER_2D_ARRAY$1 = 0x8dd7;
const samplerTypes = new Map([
[SAMPLER_2D$1, {uniformType: 'sampler2D', numberType: 'float/normalized', bindPoint: '2D'}],
[SAMPLER_CUBE$1, {uniformType: 'samplerCube', numberType: 'float/normalized', bindPoint: 'CUBE'}],
[SAMPLER_3D$1, {uniformType: 'sampler3D', numberType: 'float/normalized', bindPoint: '3D'}],
[SAMPLER_2D_SHADOW$1, {uniformType: 'sampler2D', numberType: 'float/normalized', bindPoint: '2D'}],
[SAMPLER_2D_ARRAY$1, {uniformType: 'sampler2DArray', numberType: 'float/normalized', bindPoint: '2D_ARRAY'}],
[
SAMPLER_2D_ARRAY_SHADOW$1,
{uniformType: 'sampler2DArray', numberType: 'float/normalized', bindPoint: '2D_ARRAY'},
],
[SAMPLER_CUBE_SHADOW$1, {uniformType: 'samplerCube', numberType: 'float/normalized', bindPoint: 'CUBE'}],
[INT_SAMPLER_2D$1, {uniformType: 'isampler2D', numberType: 'int', bindPoint: '2D'}],
[INT_SAMPLER_3D$1, {uniformType: 'isampler3D', numberType: 'int', bindPoint: '3D'}],
[INT_SAMPLER_CUBE$1, {uniformType: 'isamplerCube', numberType: 'int', bindPoint: 'CUBE'}],
[INT_SAMPLER_2D_ARRAY$1, {uniformType: 'isampler2DArray', numberType: 'int', bindPoint: '2D_ARRAY'}],
[UNSIGNED_INT_SAMPLER_2D$1, {uniformType: 'usampler2D', numberType: 'unsigned int', bindPoint: '2D'}],
[UNSIGNED_INT_SAMPLER_3D$1, {uniformType: 'usampler3D', numberType: 'unsigned int', bindPoint: '3D'}],
[UNSIGNED_INT_SAMPLER_CUBE$1, {uniformType: 'usamplerCube', numberType: 'unsigned int', bindPoint: 'CUBE'}],
[
UNSIGNED_INT_SAMPLER_2D_ARRAY$1,
{uniformType: 'usampler2DArray', numberType: 'unsigned int', bindPoint: '2D_ARRAY'},
],
]);
function getBindPointForSampler(type) {
return samplerTypes.get(type).bindPoint;
}
function uniformTypeIsSampler(type) {
return samplerTypes.has(type);
}
function getNumberTypeForUniformSamplerType(type) {
return samplerTypes.get(type).numberType;
}
function getUniformTypeForUniformSamplerType(type) {
return samplerTypes.get(type).uniformType;
}
const TEXTURE_2D$1 = 0x0de1;
const TEXTURE_3D$1 = 0x806f;
const TEXTURE_2D_ARRAY$1 = 0x8c1a;
const TEXTURE_CUBE_MAP$1 = 0x8513;
const TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
const TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
const TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
const TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
const TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
const TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851a;
const targetToBindPointMap = new Map([
[TEXTURE_2D$1, '2D'],
[TEXTURE_3D$1, '3D'],
[TEXTURE_CUBE_MAP$1, 'CUBE'],
[TEXTURE_CUBE_MAP_POSITIVE_X, 'CUBE'],
[TEXTURE_CUBE_MAP_NEGATIVE_X, 'CUBE'],
[TEXTURE_CUBE_MAP_POSITIVE_Y, 'CUBE'],
[TEXTURE_CUBE_MAP_NEGATIVE_Y, 'CUBE'],
[TEXTURE_CUBE_MAP_POSITIVE_Z, 'CUBE'],
[TEXTURE_CUBE_MAP_NEGATIVE_Z, 'CUBE'],
[TEXTURE_2D_ARRAY$1, '2D_ARRAY'],
]);
function getBindPointForTarget(target) {
return targetToBindPointMap.get(target);
}
const TEXTURE_BINDING_2D$1 = 0x8069;
const TEXTURE_BINDING_CUBE_MAP$1 = 0x8514;
const TEXTURE_BINDING_3D$1 = 0x806a;
const TEXTURE_BINDING_2D_ARRAY$1 = 0x8c1d;
const samplerTypeToBinding = new Map([
[SAMPLER_2D$1, TEXTURE_BINDING_2D$1],
[SAMPLER_2D_SHADOW$1, TEXTURE_BINDING_2D$1],
[SAMPLER_3D$1, TEXTURE_BINDING_3D$1],
[SAMPLER_2D_ARRAY$1, TEXTURE_BINDING_2D_ARRAY$1],
[SAMPLER_2D_ARRAY_SHADOW$1, TEXTURE_BINDING_2D_ARRAY$1],
[SAMPLER_CUBE$1, TEXTURE_BINDING_CUBE_MAP$1],
[SAMPLER_CUBE_SHADOW$1, TEXTURE_BINDING_CUBE_MAP$1],
]);
function getTextureForUnit(gl, unit, type) {
gl.activeTexture(gl.TEXTURE0 + unit);
const binding = samplerTypeToBinding.get(type);
return gl.getParameter(binding);
}
/* global WebGLTexture */
const MAX_COLOR_ATTACHMENTS = 0x8cdf;
function getMaxColorAttachments(gl) {
if (!isWebGL2(gl)) {
const ext = gl.getExtension('WEBGL_draw_buffers');
if (!ext) {
return 1;
}
}
return gl.getParameter(MAX_COLOR_ATTACHMENTS);
}
/**
* slow non-cached version
* @param {WebGLRenderingContext} gl
* @param {number} attachment
* @param {Map<WebGLTexture, [number]>} textureAttachments
*/
function addTextureAttachment(gl, attachment, textureAttachments) {
const type = gl.getFramebufferAttachmentParameter(
gl.FRAMEBUFFER,
attachment,
gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
);
if (type === gl.NONE) {
return;
}
const obj = gl.getFramebufferAttachmentParameter(
gl.FRAMEBUFFER,
attachment,
gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
);
if (obj instanceof WebGLTexture) {
if (!textureAttachments.has(obj)) {
textureAttachments.set(obj, []);
}
textureAttachments.get(obj).push(attachment);
}
}
/**
* slow non-cached version
* @param {WebGLRenderingContext} gl
*/
function checkFramebufferFeedback(gl, getWebGLObjectString) {
const framebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
if (!framebuffer) {
// drawing to canvas
return [];
}
// get framebuffer texture attachments
const maxColorAttachments = getMaxColorAttachments(gl);
const textureAttachments = new Map();
for (let i = 0; i < maxColorAttachments; ++i) {
addTextureAttachment(gl, gl.COLOR_ATTACHMENT0 + i, textureAttachments);
}
addTextureAttachment(gl, gl.DEPTH_ATTACHMENT, textureAttachments);
addTextureAttachment(gl, gl.STENCIL_ATTACHMENT, textureAttachments);
if (!isWebGL2(gl)) {
addTextureAttachment(gl, gl.DEPTH_STENCIL_ATTACHMENT, textureAttachments);
}
const oldActiveTexture = gl.getParameter(gl.ACTIVE_TEXTURE);
const program = gl.getParameter(gl.CURRENT_PROGRAM);
// get the texture units used by the current program
const numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
const errors = [];
for (let ii = 0; ii < numUniforms; ++ii) {
const {name, type, size} = gl.getActiveUniform(program, ii);
if (isBuiltIn(name) || !uniformTypeIsSampler(type)) {
continue;
}
if (size > 1) {
const baseName = name.substr(-3) === '[0]' ? name.substr(0, name.length - 3) : name;
for (let t = 0; t < size; ++t) {
errors.push(
...checkTextureUsage(
gl,
framebuffer,
textureAttachments,
program,
`${baseName}[${t}]`,
type,
getWebGLObjectString
)
);
}
} else {
errors.push(
...checkTextureUsage(gl, framebuffer, textureAttachments, program, name, type, getWebGLObjectString)
);
}
}
gl.activeTexture(oldActiveTexture);
return errors;
}
function checkTextureUsage(
gl,
framebuffer,
textureAttachments,
program,
uniformName,
uniformType,
getWebGLObjectString
) {
const location = gl.getUniformLocation(program, uniformName);
const textureUnit = gl.getUniform(program, location);
const texture = getTextureForUnit(gl, textureUnit, uniformType);
const attachments = textureAttachments.get(texture);
return attachments
? [
`${getWebGLObjectString(
texture
)} on uniform: ${uniformName} bound to texture unit ${textureUnit} is also attached to ${getWebGLObjectString(
framebuffer
)} on attachment: ${attachments.map((a) => glEnumToString(a)).join(', ')}`,
]
: [];
}
/* global navigator */
// adapted from http://stackoverflow.com/a/2401861/128511
function getBrowser() {
const userAgent = navigator.userAgent;
let m = userAgent.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
if (/trident/i.test(m[1])) {
m = /\brv[ :]+(\d+)/g.exec(userAgent) || [];
return {
name: 'IE',
version: m[1],
};
}
if (m[1] === 'Chrome') {
const temp = userAgent.match(/\b(OPR|Edge)\/(\d+)/);
if (temp) {
return {
name: temp[1].replace('OPR', 'Opera'),
version: temp[2],
};
}
}
m = m[2] ? [m[1], m[2]] : [navigator.appName, navigator.appVersion, '-?'];
const version = userAgent.match(/version\/(\d+)/i);
if (version) {
m.splice(1, 1, version[1]);
}
return {
name: m[0],
version: m[1],
};
}
/**
* @typedef {Object} StackInfo
* @property {string} url Url of line
* @property {number} lineNo line number of error
* @property {number} colNo column number of error
* @property {string} [funcName] name of function
*/
/**
* @parameter {string} stack A stack string as in `(new Error()).stack`
* @returns {StackInfo}
*/
const parseStack = (function () {
const browser = getBrowser();
let lineNdx;
let matcher;
if (/chrome|opera/i.test(browser.name)) {
lineNdx = 3;
matcher = function (line) {
const m = /at ([^(]+)*\(*(.*?):(\d+):(\d+)/.exec(line);
if (m) {
let userFnName = m[1];
let url = m[2];
const lineNo = parseInt(m[3]);
const colNo = parseInt(m[4]);
if (url === '') {
url = userFnName;
userFnName = '';
}
return {
url: url,
lineNo: lineNo,
colNo: colNo,
funcName: userFnName,
};
}
return undefined;
};
} else if (/firefox|safari/i.test(browser.name)) {
lineNdx = 2;
matcher = function (line) {
const m = /@(.*?):(\d+):(\d+)/.exec(line);
if (m) {
const url = m[1];
const lineNo = parseInt(m[2]);
const colNo = parseInt(m[3]);
return {
url: url,
lineNo: lineNo,
colNo: colNo,
};
}
return undefined;
};
}
return function stackParser(stack) {
if (matcher) {
try {
const lines = stack.split('\n');
// window.fooLines = lines;
// lines.forEach(function(line, ndx) {
// origConsole.log("#", ndx, line);
// });
return matcher(lines[lineNdx]);
} catch (e) {
// do nothing
}
}
return undefined;
};
})();
function createTextureUnits(gl) {
const textureUnits = [];
const numUnits = gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS);
for (let i = 0; i < numUnits; ++i) {
textureUnits.push(new Map());
}
return textureUnits;
}
const TEXTURE0 = 0x84c0;
const TEXTURE_2D$2 = 0x0de1;
const TEXTURE_3D$2 = 0x806f;
const TEXTURE_CUBE_MAP$2 = 0x8513;
const TEXTURE_CUBE_MAP_POSITIVE_X$1 = 0x8515;
const TEXTURE_CUBE_MAP_NEGATIVE_X$1 = 0x8516;
const TEXTURE_CUBE_MAP_POSITIVE_Y$1 = 0x8517;
const TEXTURE_CUBE_MAP_NEGATIVE_Y$1 = 0x8518;
const TEXTURE_CUBE_MAP_POSITIVE_Z$1 = 0x8519;
const TEXTURE_CUBE_MAP_NEGATIVE_Z$1 = 0x851a;
const TEXTURE_MIN_FILTER = 0x2801;
const TEXTURE_MAG_FILTER = 0x2800;
const TEXTURE_BASE_LEVEL = 0x813c; // int
const TEXTURE_MAX_LEVEL = 0x813d; // int
const TEXTURE_WRAP_S = 0x2802;
const TEXTURE_WRAP_T = 0x2803;
const REPEAT = 0x2901;
const TEXTURE_2D_ARRAY$2 = 0x8c1a;
const CLAMP_TO_EDGE = 0x812f;
const NEAREST = 0x2600;
const LINEAR = 0x2601;
const NEAREST_MIPMAP_LINEAR = 0x2702;
const texImage2DArgParersMap = new Map([
[
9,
function ([target, level, internalFormat, width, height, , format, type]) {
return {target, level, internalFormat, width, height, format, type};
},
],
[
6,
function ([target, level, internalFormat, format, type, texImageSource]) {
return {
target,
level,
internalFormat,
width: texImageSource.width,
height: texImageSource.height,
format,
type,
};
},
],
[
10,
function ([target, level, internalFormat, width, height, , format, type]) {
return {target, level, internalFormat, width, height, format, type};
},
],
]);
const ALPHA = 0x1906;
const RGB = 0x1907;
const RGBA = 0x1908;
const LUMINANCE = 0x1909;
const LUMINANCE_ALPHA = 0x190a;
const DEPTH_COMPONENT = 0x1902;
const DEPTH_STENCIL = 0x84f9;
const unsizedInternalFormats = new Set([ALPHA, LUMINANCE, LUMINANCE_ALPHA, RGB, RGBA]);
function getInternalFormatStringForInternalFormatType(internalFormat, type) {
return unsizedInternalFormats.has(internalFormat)
? `${glEnumToString(internalFormat)}/${glEnumToString(type)}`
: glEnumToString(internalFormat);
}
const targetToFaceIndex = new Map([
[TEXTURE_2D$2, 0],
[TEXTURE_3D$2, 0],
[TEXTURE_2D_ARRAY$2, 0],
[TEXTURE_CUBE_MAP$2, 0],
[TEXTURE_CUBE_MAP_POSITIVE_X$1, 0],
[TEXTURE_CUBE_MAP_NEGATIVE_X$1, 1],
[TEXTURE_CUBE_MAP_POSITIVE_Y$1, 2],
[TEXTURE_CUBE_MAP_NEGATIVE_Y$1, 3],
[TEXTURE_CUBE_MAP_POSITIVE_Z$1, 4],
[TEXTURE_CUBE_MAP_NEGATIVE_Z$1, 5],
]);
function getFaceTarget(face, type) {
if (type === TEXTURE_CUBE_MAP$2) {
return `(${glEnumToString(TEXTURE_CUBE_MAP_POSITIVE_X$1 + face)})`;
} else {
return '';
}
}
/*
const targetToBindPointMap = new Map([
[TEXTURE_2D, TEXTURE_2D],
[TEXTURE_3D, TEXTURE_3D],
[TEXTURE_2D_ARRAY, TEXTURE_2D_ARRAY],
[TEXTURE_CUBE_MAP_POSITIVE_X, TEXTURE_CUBE_MAP],
[TEXTURE_CUBE_MAP_NEGATIVE_X, TEXTURE_CUBE_MAP],
[TEXTURE_CUBE_MAP_POSITIVE_Y, TEXTURE_CUBE_MAP],
[TEXTURE_CUBE_MAP_NEGATIVE_Y, TEXTURE_CUBE_MAP],
[TEXTURE_CUBE_MAP_POSITIVE_Z, TEXTURE_CUBE_MAP],
[TEXTURE_CUBE_MAP_NEGATIVE_Z, TEXTURE_CUBE_MAP],
]);
*/
const R8 = 0x8229;
const R8_SNORM = 0x8f94;
const R16F = 0x822d;
const R32F = 0x822e;
const R8UI = 0x8232;
const R8I = 0x8231;
const RG16UI = 0x823a;
const RG16I = 0x8239;
const RG32UI = 0x823c;
const RG32I = 0x823b;
const RG8 = 0x822b;
const RG8_SNORM = 0x8f95;
const RG16F = 0x822f;
const RG32F = 0x8230;
const RG8UI = 0x8238;
const RG8I = 0x8237;
const R16UI = 0x8234;
const R16I = 0x8233;
const R32UI = 0x8236;
const R32I = 0x8235;
const RGB8 = 0x8051;
const SRGB8 = 0x8c41;
const RGB565 = 0x8d62;
const RGB8_SNORM = 0x8f96;
const R11F_G11F_B10F = 0x8c3a;
const RGB9_E5 = 0x8c3d;
const RGB16F = 0x881b;
const RGB32F = 0x8815;
const RGB8UI = 0x8d7d;
const RGB8I = 0x8d8f;
const RGB16UI = 0x8d77;
const RGB16I = 0x8d89;
const RGB32UI = 0x8d71;
const RGB32I = 0x8d83;
const RGBA8 = 0x8058;
const SRGB8_ALPHA8 = 0x8c43;
const RGBA8_SNORM = 0x8f97;
const RGB5_A1 = 0x8057;
const RGBA4 = 0x8056;
const RGB10_A2 = 0x8059;
const RGBA16F = 0x881a;
const RGBA32F = 0x8814;
const RGBA8UI = 0x8d7c;
const RGBA8I = 0x8d8e;
const RGB10_A2UI = 0x906f;
const RGBA16UI = 0x8d76;
const RGBA16I = 0x8d88;
const RGBA32I = 0x8d82;
const RGBA32UI = 0x8d70;
const DEPTH_COMPONENT16 = 0x81a5;
const DEPTH_COMPONENT24 = 0x81a6;
const DEPTH_COMPONENT32F = 0x8cac;
const DEPTH32F_STENCIL8 = 0x8cad;
const DEPTH24_STENCIL8 = 0x88f0;
/* DataType */
const BYTE$1 = 0x1400;
const UNSIGNED_BYTE$1 = 0x1401;
const SHORT$1 = 0x1402;
const UNSIGNED_SHORT$1 = 0x1403;
const INT$1 = 0x1404;
const UNSIGNED_INT$1 = 0x1405;
const FLOAT$1 = 0x1406;
const UNSIGNED_SHORT_4_4_4_4 = 0x8033;
const UNSIGNED_SHORT_5_5_5_1 = 0x8034;
const UNSIGNED_SHORT_5_6_5 = 0x8363;
const HALF_FLOAT = 0x140b;
const HALF_FLOAT_OES = 0x8d61; // Thanks Khronos for making this different >:(
const UNSIGNED_INT_2_10_10_10_REV = 0x8368;
const UNSIGNED_INT_10F_11F_11F_REV = 0x8c3b;
const UNSIGNED_INT_5_9_9_9_REV = 0x8c3e;
const FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8dad;
const UNSIGNED_INT_24_8 = 0x84fa;
const RG = 0x8227;
const RG_INTEGER = 0x8228;
const RED = 0x1903;
const RED_INTEGER = 0x8d94;
const RGB_INTEGER = 0x8d98;
const RGBA_INTEGER = 0x8d99;
function createTextureInternalFormatInfoMap() {
const textureInternalFormatInfoMap = new Map([
// unsized formats
[
ALPHA,
{
textureFormat: ALPHA,
colorRenderable: true,
textureFilterable: true,
bytesPerElement: [1, 2, 2, 4],
type: [UNSIGNED_BYTE$1],
},
],
[
LUMINANCE,
{
textureFormat: LUMINANCE,
colorRenderable: true,
textureFilterable: true,
bytesPerElement: [1, 2, 2, 4],
type: [UNSIGNED_BYTE$1],
},
],
[
LUMINANCE_ALPHA,
{
textureFormat: LUMINANCE_ALPHA,
colorRenderable: true,
textureFilterable: true,
bytesPerElement: [2, 4, 4, 8],
type: [UNSIGNED_BYTE$1],
},
],
[
RGB,
{
textureFormat: RGB,
colorRenderable: true,
textureFilterable: true,
bytesPerElement: [3, 6, 6, 12, 2],
type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_5_6_5],
},
],
[
RGBA,
{
textureFormat: RGBA,
colorRenderable: true,
textureFilterable: true,
bytesPerElement: [4, 8, 8, 16, 2, 2],
type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_4_4_4_4, UNSIGNED_SHORT_5_5_5_1],
},
],
// sized formats
[
R8,
{
textureFormat: RED,
colorRenderable: true,
textureFilterable: true,
bytesPerElement: [1],
type: [UNSIGNED_BYTE$1],
},
],
[
R8_SNORM,
{
textureFormat: RED,
colorRenderable: false,
textureFilterable: true,
bytesPerElement: [1],
type: [BYTE$1],
},
],
[
R16F,
{
textureFormat: RED,
colorRenderable: false,
textureFilterable: true,
bytesPerElement: [4, 2],
type: [FLOAT$1, HALF_FLOAT],
},
],
[
R32F,
{
textureFormat: RED,
colorRenderable: false,
textureFilterable: false,
bytesPerElement: [4],
type: [FLOAT$1],
},
],
[
R8UI,
{
textureFormat: RED_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [1],
type: [UNSIGNED_BYTE$1],
},
],
[
R8I,
{
textureFormat: RED_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [1],
type: [BYTE$1],
},
],
[
R16UI,
{
textureFormat: RED_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [2],
type: [UNSIGNED_SHORT$1],
},
],
[
R16I,
{
textureFormat: RED_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [2],
type: [SHORT$1],
},
],
[
R32UI,
{
textureFormat: RED_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [4],
type: [UNSIGNED_INT$1],
},
],
[
R32I,
{
textureFormat: RED_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [4],
type: [INT$1],
},
],
[
RG8,
{
textureFormat: RG,
colorRenderable: true,
textureFilterable: true,
bytesPerElement: [2],
type: [UNSIGNED_BYTE$1],
},
],
[
RG8_SNORM,
{
textureFormat: RG,
colorRenderable: false,
textureFilterable: true,
bytesPerElement: [2],
type: [BYTE$1],
},
],
[
RG16F,
{
textureFormat: RG,
colorRenderable: false,
textureFilterable: true,
bytesPerElement: [8, 4],
type: [FLOAT$1, HALF_FLOAT],
},
],
[
RG32F,
{
textureFormat: RG,
colorRenderable: false,
textureFilterable: false,
bytesPerElement: [8],
type: [FLOAT$1],
},
],
[
RG8UI,
{
textureFormat: RG_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [2],
type: [UNSIGNED_BYTE$1],
},
],
[
RG8I,
{
textureFormat: RG_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [2],
type: [BYTE$1],
},
],
[
RG16UI,
{
textureFormat: RG_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [4],
type: [UNSIGNED_SHORT$1],
},
],
[
RG16I,
{
textureFormat: RG_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [4],
type: [SHORT$1],
},
],
[
RG32UI,
{
textureFormat: RG_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [8],
type: [UNSIGNED_INT$1],
},
],
[
RG32I,
{
textureFormat: RG_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [8],
type: [INT$1],
},
],
[
RGB8,
{
textureFormat: RGB,
colorRenderable: true,
textureFilterable: true,
bytesPerElement: [3],
type: [UNSIGNED_BYTE$1],
},
],
[
SRGB8,
{
textureFormat: RGB,
colorRenderable: false,
textureFilterable: true,
bytesPerElement: [3],
type: [UNSIGNED_BYTE$1],
},
],
[
RGB565,
{
textureFormat: RGB,
colorRenderable: true,
textureFilterable: true,
bytesPerElement: [3, 2],
type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_5_6_5],
},
],
[
RGB8_SNORM,
{
textureFormat: RGB,
colorRenderable: false,
textureFilterable: true,
bytesPerElement: [3],
type: [BYTE$1],
},
],
[
R11F_G11F_B10F,
{
textureFormat: RGB,
colorRenderable: false,
textureFilterable: true,
bytesPerElement: [12, 6, 4],
type: [FLOAT$1, HALF_FLOAT, UNSIGNED_INT_10F_11F_11F_REV],
},
],
[
RGB9_E5,
{
textureFormat: RGB,
colorRenderable: false,
textureFilterable: true,
bytesPerElement: [12, 6, 4],
type: [FLOAT$1, HALF_FLOAT, UNSIGNED_INT_5_9_9_9_REV],
},
],
[
RGB16F,
{
textureFormat: RGB,
colorRenderable: false,
textureFilterable: true,
bytesPerElement: [12, 6],
type: [FLOAT$1, HALF_FLOAT],
},
],
[
RGB32F,
{
textureFormat: RGB,
colorRenderable: false,
textureFilterable: false,
bytesPerElement: [12],
type: [FLOAT$1],
},
],
[
RGB8UI,
{
textureFormat: RGB_INTEGER,
colorRenderable: false,
textureFilterable: false,
bytesPerElement: [3],
type: [UNSIGNED_BYTE$1],
},
],
[
RGB8I,
{
textureFormat: RGB_INTEGER,
colorRenderable: false,
textureFilterable: false,
bytesPerElement: [3],
type: [BYTE$1],
},
],
[
RGB16UI,
{
textureFormat: RGB_INTEGER,
colorRenderable: false,
textureFilterable: false,
bytesPerElement: [6],
type: [UNSIGNED_SHORT$1],
},
],
[
RGB16I,
{
textureFormat: RGB_INTEGER,
colorRenderable: false,
textureFilterable: false,
bytesPerElement: [6],
type: [SHORT$1],
},
],
[
RGB32UI,
{
textureFormat: RGB_INTEGER,
colorRenderable: false,
textureFilterable: false,
bytesPerElement: [12],
type: [UNSIGNED_INT$1],
},
],
[
RGB32I,
{
textureFormat: RGB_INTEGER,
colorRenderable: false,
textureFilterable: false,
bytesPerElement: [12],
type: [INT$1],
},
],
[
RGBA8,
{
textureFormat: RGBA,
colorRenderable: true,
textureFilterable: true,
bytesPerElement: [4],
type: [UNSIGNED_BYTE$1],
},
],
[
SRGB8_ALPHA8,
{
textureFormat: RGBA,
colorRenderable: true,
textureFilterable: true,
bytesPerElement: [4],
type: [UNSIGNED_BYTE$1],
},
],
[
RGBA8_SNORM,
{
textureFormat: RGBA,
colorRenderable: false,
textureFilterable: true,
bytesPerElement: [4],
type: [BYTE$1],
},
],
[
RGB5_A1,
{
textureFormat: RGBA,
colorRenderable: true,
textureFilterable: true,
bytesPerElement: [4, 2, 4],
type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_5_5_5_1, UNSIGNED_INT_2_10_10_10_REV],
},
],
[
RGBA4,
{
textureFormat: RGBA,
colorRenderable: true,
textureFilterable: true,
bytesPerElement: [4, 2],
type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_4_4_4_4],
},
],
[
RGB10_A2,
{
textureFormat: RGBA,
colorRenderable: true,
textureFilterable: true,
bytesPerElement: [4],
type: [UNSIGNED_INT_2_10_10_10_REV],
},
],
[
RGBA16F,
{
textureFormat: RGBA,
colorRenderable: false,
textureFilterable: true,
bytesPerElement: [16, 8],
type: [FLOAT$1, HALF_FLOAT],
},
],
[
RGBA32F,
{
textureFormat: RGBA,
colorRenderable: false,
textureFilterable: false,
bytesPerElement: [16],
type: [FLOAT$1],
},
],
[
RGBA8UI,
{
textureFormat: RGBA_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [4],
type: [UNSIGNED_BYTE$1],
},
],
[
RGBA8I,
{
textureFormat: RGBA_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [4],
type: [BYTE$1],
},
],
[
RGB10_A2UI,
{
textureFormat: RGBA_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [4],
type: [UNSIGNED_INT_2_10_10_10_REV],
},
],
[
RGBA16UI,
{
textureFormat: RGBA_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [8],
type: [UNSIGNED_SHORT$1],
},
],
[
RGBA16I,
{
textureFormat: RGBA_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [8],
type: [SHORT$1],
},
],
[
RGBA32I,
{
textureFormat: RGBA_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [16],
type: [INT$1],
},
],
[
RGBA32UI,
{
textureFormat: RGBA_INTEGER,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [16],
type: [UNSIGNED_INT$1],
},
],
// Sized Internal
[
DEPTH_COMPONENT16,
{
textureFormat: DEPTH_COMPONENT,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [2, 4],
type: [UNSIGNED_SHORT$1, UNSIGNED_INT$1],
},
],
[
DEPTH_COMPONENT24,
{
textureFormat: DEPTH_COMPONENT,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [4],
type: [UNSIGNED_INT$1],
},
],
[
DEPTH_COMPONENT32F,
{
textureFormat: DEPTH_COMPONENT,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [4],
type: [FLOAT$1],
},
],
[
DEPTH24_STENCIL8,
{
textureFormat: DEPTH_STENCIL,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [4],
type: [UNSIGNED_INT_24_8],
},
],
[
DEPTH32F_STENCIL8,
{
textureFormat: DEPTH_STENCIL,
colorRenderable: true,
textureFilterable: false,
bytesPerElement: [4],
type: [FLOAT_32_UNSIGNED_INT_24_8_REV],
},
],
]);
textureInternalFormatInfoMap.forEach((info) => {
info.bytesPerElementMap = {};
info.bytesPerElement.forEach(function (bytesPerElement, ndx) {
const type = info.type[ndx];
info.bytesPerElementMap[type] = bytesPerElement;
});
});
const internalFormatStringToFormatInfoMap = new Map();
textureInternalFormatInfoMap.forEach((info, internalFormat) => {
if (unsizedInternalFormats.has(internalFormat)) {
info.type.forEach((type) => {
internalFormatStringToFormatInfoMap.set(
getInternalFormatStringForInternalFormatType(internalFormat, type),
info
);
});
} else {
internalFormatStringToFormatInfoMap.set(
getInternalFormatStringForInternalFormatType(internalFormat),
info
);
}
});
return {
textureInternalFormatInfoMap,
internalFormatStringToFormatInfoMap,
};
}
function isPowerOf2(value) {
return (value & (value - 1)) === 0;
}
function computeNumMipsNeeded(width, height = 0, depth = 0) {
return (Math.log2(Math.max(width, height, depth)) | 0) + 1;
}
function insertIf(condition, ...elements) {
return condition ? elements : [];
}
function getNPotIssues(width, height) {
return [
...insertIf(!isPowerOf2(width), `width(${width}) is not a power of 2`),
...insertIf(!isPowerOf2(height), `height(${height}) is not a power of 2`),
].join(' and ');
}
function getClampToEdgeIssues(wrapS, wrapT) {
return [
...insertIf(wrapS !== CLAMP_TO_EDGE, `TEXTURE_WRAP_S (${glEnumToString(wrapS)}) is not CLAMP_TO_EDGE`),
...insertIf(wrapT !== CLAMP_TO_EDGE, `TEXTURE_WRAP_T (${glEnumToString(wrapT)}) is not CLAMP_TO_EDGE`),
].join(' and ');
}
function getNumberTypeForInternalFormat(internalFormat) {
const str = glEnumToString(internalFormat);
if (str.endsWith('UI')) {
return 'unsigned int';
}
if (str.endsWith('I')) {
return 'int';
}
return 'float/normalized';
}
function getDimensionsString(type, width, height, depth) {
return type === TEXTURE_2D$2 || type === TEXTURE_CUBE_MAP$2
? `${width}x${height}`
: `${width}x${height}x${depth}`;
}
class TextureManager {
constructor(gl) {
const isWebGL2$1 = isWebGL2(gl);
const needPOT = !isWebGL2$1;
const extensions = new Set();
const textureToTextureInfoMap = new Map();
const samplerToParametersMap = new Map();
const textureUnits = createTextureUnits(gl);
const maxMips = computeNumMipsNeeded(gl.getParameter(gl.MAX_TEXTURE_SIZE));
const {internalFormatStringToFormatInfoMap} = createTextureInternalFormatInfoMap();
let activeTextureUnitIndex = 0;
let activeTextureUnit = textureUnits[0];
this.numTextureUnits = textureUnits.length;
function recomputeRenderability(textureInfo) {
textureInfo.notRenderable = computeRenderability(textureInfo, textureInfo.parameters);
}
function recomputeAllTextureUnrenderability() {
textureToTextureInfoMap.forEach(recomputeRenderability);
}
function computeRenderability(textureInfo, parameters) {
const {type, mips} = textureInfo;
const baseLevel = parameters.get(TEXTURE_BASE_LEVEL) || 0;
const maxLevel = parameters.get(TEXTURE_MAX_LEVEL) || maxMips;
if (maxLevel < baseLevel) {
return `TEXTURE_MAX_LEVEL(${maxLevel}) is less than TEXTURE_BASE_LEVEL(${baseLevel})`;
}
const baseLevelFaces = mips[baseLevel];
if (!baseLevelFaces) {
return 'no base level mip ${baseLevel}';
}
const baseMipFace = baseLevelFaces[0];
if (!baseMipFace) {
return 'TEXTURE_CUBE_MAP_POSITIVE_X face does not exist';
}
const {
width: baseWidth,
height: baseHeight,
depth: baseDepth,
// internalFormat: baseInternalFormat,
internalFormatString: baseInternalFormatString,
} = baseMipFace;
const numFaces = type === TEXTURE_CUBE_MAP$2 ? 6 : 1;
const minFilter = parameters.get(TEXTURE_MIN_FILTER);
const internalFormatInfo = internalFormatStringToFormatInfoMap.get(baseInternalFormatString);
// there is no format info for compressed texture ATM.
// we could add it but AFAIK compressed textures are colorFilterable
// so for now let's just not do the check if we don't know about the format
if (internalFormatInfo) {
const textureFilterable = internalFormatInfo.textureFilterable;
if (!textureFilterable) {
if (minFilter !== NEAREST) {
return `texture of type (${baseInternalFormatString}) is not filterable but TEXTURE_MIN_FILTER is set to ${glEnumToString(
minFilter
)}`;
} else {
const magFilter = parameters.get(TEXTURE_MAG_FILTER);
if (magFilter !== NEAREST) {
return `texture of type (${baseInternalFormatString}) is not filterable but TEXTURE_MAG_FILTER is set to ${glEnumToString(
magFilter
)}`;
}
}
}
}
const numMipsNeeded =
minFilter === LINEAR || minFilter === NEAREST
? 1
: computeNumMipsNeeded(baseWidth, baseHeight, baseDepth);
{
let mipWidth = baseWidth;
let mipHeight = baseHeight;
let mipDepth = baseDepth;
const lastMip = Math.min(maxLevel, baseLevel + numMipsNeeded - 1);
for (let mipLevel = baseLevel; mipLevel <= lastMip; ++mipLevel) {
const faceMips = mips[mipLevel];
if (!faceMips) {
return `filtering is set to use mips (TEXTURE_MIN_FILTER = ${glEnumToString(
minFilter
)}) but mip level ${mipLevel} does not exist`;
}
for (let face = 0; face < numFaces; ++face) {
const mip = faceMips[face];
if (!mip) {
return `filtering is set to use mips (TEXTURE_MIN_FILTER = ${glEnumToString(
minFilter
)}) but mip level ${mipLevel}${getFaceTarget(face, type)} does not exist`;
}
if (mip.width !== mipWidth || mip.height !== mipHeight || mip.depth !== mipDepth) {
return `mip level ${mipLevel}${getFaceTarget(
face,
type
)} needs to be ${getDimensionsString(
type,
mipWidth,
mipHeight,
mipDepth
)} but it is ${getDimensionsString(type, mip.width, mip.height, mip.depth)}`;
}
if (mip.internalFormatString !== baseInternalFormatString) {
return `mip level ${mipLevel}${getFaceTarget(face, type)}'s internal format ${
mip.internalFormatString
} does not match mip level 0's internal format ${baseInternalFormatString}`;
}
}
mipWidth = Math.max(1, (mipWidth / 2) | 0);
mipHeight = Math.max(1, (mipHeight / 2) | 0);
if (type !== TEXTURE_2D_ARRAY$2) {
mipDepth = Math.max(1, (mipDepth / 2) | 0);
}
}
}
if (needPOT) {
if (!isPowerOf2(baseWidth) || !isPowerOf2(baseHeight)) {
if (numMipsNeeded > 1) {
return `texture's ${getNPotIssues(
baseWidth,
baseHeight
)} but TEXTURE_MIN_FILTER (${glEnumToString(minFilter)}) is set to need mips`;
}
const wrapS = parameters.get(TEXTURE_WRAP_S);
const wrapT = parameters.get(TEXTURE_WRAP_T);
if (wrapS !== CLAMP_TO_EDGE || wrapT !== CLAMP_TO_EDGE) {
return `texture's ${getNPotIssues(baseWidth, baseHeight)} but ${getClampToEdgeIssues(
wrapS,
wrapT
)}.`;
}
}
}
if (type === TEXTURE_CUBE_MAP$2) {
if (baseWidth !== baseHeight) {
return `texture is CUBE_MAP but dimensions ${baseWidth}x${baseHeight} are not square`;
}
}
return undefined;
}
function getTextureInfoForTarget(target) {
const bindPoint = getBindPointForTarget(target);
const texture = activeTextureUnit.get(bindPoint);
return textureToTextureInfoMap.get(texture);
}
function getMipInfoForTarget(target, level) {
const textureInfo = getTextureInfoForTarget(target);
const faceIndex = targetToFaceIndex.get(target);
return textureInfo.mips[level][faceIndex];
}
function setTexParameterForTarget(target, pname, value) {
const textureInfo = getTextureInfoForTarget(target);
textureInfo.parameters.set(pname, value);
recomputeRenderability(textureInfo);
}
function removeFromTextureUnits(type, obj) {
for (let i = 0; i < textureUnits.length; ++i) {
const unit = textureUnits[i];
if (unit.get(type) === obj) {
unit.set(type, null);
}
}
}
function getInternalFormatStringForTextureInfo(textureInfo) {
const {mips, parameters} = textureInfo;
const baseLevel = parameters.get(TEXTURE_BASE_LEVEL) || 0;
const baseFaces = mips[baseLevel];
if (!baseFaces) {
return '';
}
const baseMipFace = baseFaces[0];
if (!baseMipFace) {
return '';
}
return baseMipFace.internalFormatString;
}
function addInternalFormatStringInfos(type, textureFilterableExtensionName) {
const textureFilterable = extensions.has(textureFilterableExtensionName);
[RGBA, RGB, LUMINANCE, LUMINANCE_ALPHA, ALPHA].forEach((internalFormat) => {
internalFormatStringToFormatInfoMap.set(