UNPKG

@doegis/core

Version:

DOE GIS API

3 lines (1 loc) 11.9 kB
import"../../core/has.js";import{isPowerOfTwo as t}from"../../core/mathUtils.js";import{isSome as e,isNone as i,unwrap as r}from"../../core/maybe.js";import{checkWebGLError as o}from"./checkWebGLError.js";import{ContextType as s}from"./context-util.js";import{TextureType as a,TextureSamplingMode as n,TextureWrapMode as l,ResourceType as h,PixelType as p,PixelFormat as _,SizedPixelFormat as m,CompressedTextureFormat as d}from"./enums.js";const u={target:a.TEXTURE_2D,samplingMode:n.LINEAR,wrapMode:l.REPEAT,flipped:!1,hasMipmap:!1,isOpaque:!1,unpackAlignment:4,preMultiplyAlpha:!1,isImmutable:!1},c=4;let E=class{constructor(t,e,i=null){this._context=t,this.type="texture",this._glName=null,this._samplingModeDirty=!1,this._wrapModeDirty=!1,this._wasImmutablyAllocated=!1,t.instanceCounter.increment(h.Texture,this),this._descriptor={...u,...e};for(const r in u){void 0===this._descriptor[r]&&(this._descriptor[r]=u[r])}if(t.type!==s.WEBGL2&&(this._descriptor.isImmutable&&(this._descriptor.isImmutable=!1),A(this._descriptor.target)))throw new Error("3D and array textures are not supported in WebGL1");this._descriptor.target===a.TEXTURE_CUBE_MAP?this._setDataCubeMap(i):this.setData(i)}get glName(){return this._glName}get descriptor(){return this._descriptor}get isDirty(){return this._samplingModeDirty||this._wrapModeDirty}dispose(){this._context.gl&&this._glName&&(this._context.unbindTexture(this),this._context.gl.deleteTexture(this._glName),this._glName=null,this._context.instanceCounter.decrement(h.Texture,this))}release(){this.dispose()}resize(t,e){const i=this._descriptor;if(i.width!==t||i.height!==e){if(this._wasImmutablyAllocated)throw new Error("Immutable textures can't be resized!");i.width=t,i.height=e,this._descriptor.target===a.TEXTURE_CUBE_MAP?this._setDataCubeMap(null):this.setData(null)}}_setDataCubeMap(t=null){for(let e=a.TEXTURE_CUBE_MAP_POSITIVE_X;e<=a.TEXTURE_CUBE_MAP_NEGATIVE_Z;e++)this._setData(t,e)}setData(t){this._setData(t)}_setData(t,i){if(!this._context||!this._context.gl)return;const r=this._context.gl;this._glName||(this._glName=r.createTexture()),void 0===t&&(t=null);const s=this._descriptor,a=i??s.target,n=A(a);null===t&&(s.width=s.width||c,s.height=s.height||c,n&&(s.depth=s.depth??1));const l=this._context.bindTexture(this,E.TEXTURE_UNIT_FOR_UPDATES);this._context.setActiveTexture(E.TEXTURE_UNIT_FOR_UPDATES),E._validateTexture(this._context,s),this._configurePixelStorage(),o(r);const h=s.pixelFormat;let p=s.internalFormat??this._deriveInternalFormat(h,s.dataType);if(f(t)){let e=t.width,i=t.height;const l=1;t instanceof HTMLVideoElement&&(e=t.videoWidth,i=t.videoHeight),s.width&&s.height,n&&s.depth,s.isImmutable&&!this._wasImmutablyAllocated&&this._texStorage(a,p,s.hasMipmap,e,i,l),this._texImage(a,0,p,e,i,l,t),o(r),s.hasMipmap&&this.generateMipmap(),void 0===s.width&&(s.width=e),void 0===s.height&&(s.height=i),n&&void 0===s.depth&&(s.depth=l)}else{const{width:i,height:l,depth:h}=s;if(null==i||null==l)throw new Error("Width and height must be specified!");if(n&&null==h)throw new Error("Depth must be specified!");if(s.isImmutable&&!this._wasImmutablyAllocated&&this._texStorage(a,p,s.hasMipmap,i,l,h),r.DEPTH24_STENCIL8&&p===r.DEPTH_STENCIL&&(p=r.DEPTH24_STENCIL8),x(t)){const o=t.levels,n=w(a,i,l,h),_=Math.min(n-1,o.length-1);e(this._context.gl2)?r.texParameteri(s.target,this._context.gl2.TEXTURE_MAX_LEVEL,_):s.hasMipmap=s.hasMipmap&&n===o.length;const m=p;if(!T(m))throw new Error("Attempting to use compressed data with an umcompressed format!");this._forEachMipmapLevel(((t,e,i,r)=>{const s=o[Math.min(t,o.length-1)];this._compressedTexImage(a,t,m,e,i,r,s)}),_)}else e(t)?(this._texImage(a,0,p,i,l,h,t),o(r),s.hasMipmap&&this.generateMipmap()):this._forEachMipmapLevel(((t,e,i,s)=>{this._texImage(a,t,p,e,i,s,null),o(r)}))}E._applySamplingMode(r,this._descriptor),E._applyWrapMode(r,this._descriptor),E._applyAnisotropicFilteringParameters(this._context,this._descriptor),o(r),this._context.bindTexture(l,E.TEXTURE_UNIT_FOR_UPDATES)}updateData(t,r,o,s,a,n,l=0){n||console.error("An attempt to use uninitialized data!"),this._glName||console.error("An attempt to update uninitialized texture!");const h=this._context.gl,p=this._descriptor,{pixelFormat:_,dataType:m,target:d,isImmutable:u}=p,c=p.internalFormat??this._deriveInternalFormat(_,m);if(u&&!this._wasImmutablyAllocated)throw new Error("Cannot update immutable texture before allocation!");const g=this._context.bindTexture(this,E.TEXTURE_UNIT_FOR_UPDATES,!0);if((r<0||o<0||s>p.width||a>p.height||r+s>p.width||o+a>p.height)&&console.error("An attempt to update out of bounds of the texture!"),this._configurePixelStorage(),l){if(i(this._context.gl2))return void console.error("Webgl2 must be enabled to use dataRowOffset!");h.pixelStorei(this._context.gl2.UNPACK_SKIP_ROWS,l)}if(f(n)?e(this._context.gl2)?this._context.gl2.texSubImage2D(d,t,r,o,s,a,_,m,n):h.texSubImage2D(d,t,r,o,_,m,n):x(n)?h.compressedTexSubImage2D(d,t,r,o,s,a,c,n.levels[t]):h.texSubImage2D(d,t,r,o,s,a,_,m,n),l){if(i(this._context.gl2))return void console.error("Webgl2 must be enabled to use dataRowOffset!");h.pixelStorei(this._context.gl2.UNPACK_SKIP_ROWS,0)}this._context.bindTexture(g,E.TEXTURE_UNIT_FOR_UPDATES)}updateData3D(t,e,r,o,s,a,n,l){l||console.error("An attempt to use uninitialized data!"),this._glName||console.error("An attempt to update uninitialized texture!");const h=this._context.gl2;if(i(h))throw new Error("3D textures are not supported in WebGL1");const p=this._descriptor,{pixelFormat:_,dataType:m,isImmutable:d,target:u}=p,c=p.internalFormat??this._deriveInternalFormat(_,m);if(d&&!this._wasImmutablyAllocated)throw new Error("Cannot update immutable texture before allocation!");A(u)||console.warn("Attempting to set 3D texture data on a non-3D texture");const g=this._context.bindTexture(this,E.TEXTURE_UNIT_FOR_UPDATES);if(this._context.setActiveTexture(E.TEXTURE_UNIT_FOR_UPDATES),(e<0||r<0||o<0||s>p.width||a>p.height||n>p.depth||e+s>p.width||r+a>p.height||o+n>p.depth)&&console.error("An attempt to update out of bounds of the texture!"),this._configurePixelStorage(),x(l))l=l.levels[t],h.compressedTexSubImage3D(u,t,e,r,o,s,a,n,c,l);else{const i=l;h.texSubImage3D(u,t,e,r,o,s,a,n,_,m,i)}this._context.bindTexture(g,E.TEXTURE_UNIT_FOR_UPDATES)}generateMipmap(){const t=this._descriptor;if(!t.hasMipmap){if(this._wasImmutablyAllocated)throw new Error("Cannot add mipmaps to immutable texture after allocation");t.hasMipmap=!0,this._samplingModeDirty=!0,E._validateTexture(this._context,t)}t.samplingMode===n.LINEAR?(this._samplingModeDirty=!0,t.samplingMode=n.LINEAR_MIPMAP_NEAREST):t.samplingMode===n.NEAREST&&(this._samplingModeDirty=!0,t.samplingMode=n.NEAREST_MIPMAP_NEAREST);const e=this._context.bindTexture(this,E.TEXTURE_UNIT_FOR_UPDATES);this._context.setActiveTexture(E.TEXTURE_UNIT_FOR_UPDATES);this._context.gl.generateMipmap(t.target),this._context.bindTexture(e,E.TEXTURE_UNIT_FOR_UPDATES)}setSamplingMode(t){t!==this._descriptor.samplingMode&&(this._descriptor.samplingMode=t,this._samplingModeDirty=!0)}setWrapMode(t){t!==this._descriptor.wrapMode&&(this._descriptor.wrapMode=t,E._validateTexture(this._context,this._descriptor),this._wrapModeDirty=!0)}applyChanges(){const t=this._context.gl,e=this._descriptor;this._samplingModeDirty&&(E._applySamplingMode(t,e),this._samplingModeDirty=!1),this._wrapModeDirty&&(E._applyWrapMode(t,e),this._wrapModeDirty=!1)}_deriveInternalFormat(t,e){if(this._context.type===s.WEBGL1)return t;switch(e){case p.FLOAT:switch(t){case _.RGBA:return m.RGBA32F;case _.RGB:return m.RGB32F;default:throw new Error("Unable to derive format")}case p.UNSIGNED_BYTE:switch(t){case _.RGBA:return m.RGBA8;case _.RGB:return m.RGB8}default:return t}}_configurePixelStorage(){const t=this._context.gl,{unpackAlignment:e,flipped:i,preMultiplyAlpha:r}=this._descriptor;t.pixelStorei(t.UNPACK_ALIGNMENT,e),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,i?1:0),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,r?1:0)}_texStorage(t,e,r,o,s,a){const n=this._context.gl2;if(i(n))throw new Error("Immutable textures are not supported in WebGL1");if(!g(e))throw new Error("Immutable textures must have a sized internal format");if(!this._descriptor.isImmutable)return;const l=r?w(t,o,s,a):1;if(A(t)){if(null==a)throw new Error("Missing depth dimension for 3D texture upload");n.texStorage3D(t,l,e,o,s,a)}else n.texStorage2D(t,l,e,o,s);this._wasImmutablyAllocated=!0}_texImage(t,i,o,a,n,l,h){const p=this._context.gl;let _=null;const m=this._context.type===s.WEBGL2,d=A(t),{isImmutable:u,pixelFormat:c,dataType:E}=this._descriptor;if(m&&(_=p),m||!f(h))if(u){if(e(h)){const e=h;if(d){if(null==l)throw new Error("Missing depth dimension for 3D texture upload");_.texSubImage3D(t,i,0,0,0,a,n,l,c,E,e)}else p.texSubImage2D(t,i,0,0,a,n,c,E,e)}}else{const e=r(h);if(d){if(null==l)throw new Error("Missing depth dimension for 3D texture upload");_.texImage3D(t,i,o,a,n,l,0,c,E,e)}else p.texImage2D(t,i,o,a,n,0,c,E,e)}else p.texImage2D(t,0,o,c,E,h)}_compressedTexImage(t,i,r,o,a,n,l){const h=this._context.gl;let p=null;const _=A(t),m=this._descriptor.isImmutable;if(_){if(this._context.type!==s.WEBGL2)throw new Error("3D textures are not supported in WebGL1");p=h}if(m){if(e(l))if(_){if(null==n)throw new Error("Missing depth dimension for 3D texture upload");p.compressedTexSubImage3D(t,i,0,0,0,o,a,n,r,l)}else h.compressedTexSubImage2D(t,i,0,0,o,a,r,l)}else if(_){if(null==n)throw new Error("Missing depth dimension for 3D texture upload");p.compressedTexImage3D(t,i,r,o,a,n,0,l)}else h.compressedTexImage2D(t,i,r,o,a,0,l)}_forEachMipmapLevel(t,e=1/0){let{width:i,height:r,depth:o,hasMipmap:s,target:n}=this._descriptor;const l=n===a.TEXTURE_3D;if(null==i||null==r||l&&null==o)throw new Error("Missing texture dimensions for mipmap calculation");for(let a=0;t(a,i,r,o),s&&(1!==i||1!==r||l&&1!==o)&&!(a>=e);++a)i=Math.max(1,i>>1),r=Math.max(1,r>>1),l&&(o=Math.max(1,o>>1))}static _validateTexture(e,i){(null!=i.width&&i.width<0||null!=i.height&&i.height<0||null!=i.depth&&i.depth<0)&&console.error("Negative dimension parameters are not allowed!");const r=e.type===s.WEBGL2,o=null!=i.width&&t(i.width)&&null!=i.height&&t(i.height);r||!i.isImmutable&&!A(i.target)||console.error("Immutable and 3D-like textures are not supported in WebGL1!"),r||o||("number"==typeof i.wrapMode?i.wrapMode!==l.CLAMP_TO_EDGE&&console.error("Non-power-of-two textures must have a wrap mode of CLAMP_TO_EDGE!"):i.wrapMode.s===l.CLAMP_TO_EDGE&&i.wrapMode.t===l.CLAMP_TO_EDGE||console.error("Non-power-of-two textures must have a wrap mode of CLAMP_TO_EDGE!"),i.hasMipmap&&console.error("Mipmapping requires power-of-two textures!"))}static _applySamplingMode(t,e){let i=e.samplingMode,r=e.samplingMode;i===n.LINEAR_MIPMAP_NEAREST||i===n.LINEAR_MIPMAP_LINEAR?(i=n.LINEAR,e.hasMipmap||(r=n.LINEAR)):i!==n.NEAREST_MIPMAP_NEAREST&&i!==n.NEAREST_MIPMAP_LINEAR||(i=n.NEAREST,e.hasMipmap||(r=n.NEAREST)),t.texParameteri(e.target,t.TEXTURE_MAG_FILTER,i),t.texParameteri(e.target,t.TEXTURE_MIN_FILTER,r)}static _applyWrapMode(t,e){"number"==typeof e.wrapMode?(t.texParameteri(e.target,t.TEXTURE_WRAP_S,e.wrapMode),t.texParameteri(e.target,t.TEXTURE_WRAP_T,e.wrapMode)):(t.texParameteri(e.target,t.TEXTURE_WRAP_S,e.wrapMode.s),t.texParameteri(e.target,t.TEXTURE_WRAP_T,e.wrapMode.t))}static _applyAnisotropicFilteringParameters(t,e){const i=t.capabilities.textureFilterAnisotropic;if(!i)return;t.gl.texParameterf(e.target,i.TEXTURE_MAX_ANISOTROPY,e.maxAnisotropy??1)}};function g(t){return t in m}function T(t){return t in d}function x(t){return e(t)&&"type"in t&&"compressed"===t.type}function M(t){return e(t)&&"byteLength"in t}function f(t){return e(t)&&!x(t)&&!M(t)}function A(t){return t===a.TEXTURE_3D||t===a.TEXTURE_2D_ARRAY}function w(t,e,i,r=1){let o=Math.max(e,i);return t===a.TEXTURE_3D&&(o=Math.max(o,r)),Math.round(Math.log(o)/Math.LN2)+1}E.TEXTURE_UNIT_FOR_UPDATES=0;export{E as Texture};