/* All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://js.arcgis.com/4.25/esri/copyright.txt for details. */ import"../../core/has.js";import{isPowerOfTwo as t}from"../../core/mathUtils.js";import{isSome as e,unwrap as i}from"../../core/maybe.js";import{checkWebGLError as r}from"./checkWebGLError.js";import{ContextType as o}from"./context-util.js";import{TextureType as s,TextureSamplingMode as a,TextureWrapMode as n,ResourceType as l,PixelType as h,PixelFormat as p,SizedPixelFormat as _,CompressedTextureFormat as m}from"./enums.js";import d from"./capabilities/isWebGL2Context.js";const u={target:s.TEXTURE_2D,samplingMode:a.LINEAR,wrapMode:n.REPEAT,flipped:!1,hasMipmap:!1,isOpaque:!1,unpackAlignment:4,preMultiplyAlpha:!1,isImmutable:!1},c=4;class E{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(l.Texture,this),this._descriptor={...u,...e};for(const r in u){void 0===this._descriptor[r]&&(this._descriptor[r]=u[r])}if(t.type!==o.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===s.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(l.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===s.TEXTURE_CUBE_MAP?this._setDataCubeMap(null):this.setData(null)}}_setDataCubeMap(t=null){for(let e=s.TEXTURE_CUBE_MAP_POSITIVE_X;e<=s.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 o=this._context.gl;this._glName||(this._glName=o.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(),r(o);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),r(o),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),o.DEPTH24_STENCIL8&&p===o.DEPTH_STENCIL&&(p=o.DEPTH24_STENCIL8),x(t)){const e=t.levels,r=w(a,i,l,h),n=Math.min(r-1,e.length-1);d(o)?o.texParameteri(s.target,o.TEXTURE_MAX_LEVEL,n):s.hasMipmap=s.hasMipmap&&r===e.length;const _=p;if(!g(_))throw new Error("Attempting to use compressed data with an umcompressed format!");this._forEachMipmapLevel(((t,i,r,o)=>{const s=e[Math.min(t,e.length-1)];this._compressedTexImage(a,t,_,i,r,o,s)}),n)}else e(t)?(this._texImage(a,0,p,i,l,h,t),r(o),s.hasMipmap&&this.generateMipmap()):this._forEachMipmapLevel(((t,e,i,s)=>{this._texImage(a,t,p,e,i,s,null),r(o)}))}E._applySamplingMode(o,this._descriptor),E._applyWrapMode(o,this._descriptor),E._applyAnisotropicFilteringParameters(this._context,this._descriptor),r(o),this._context.bindTexture(l,E.TEXTURE_UNIT_FOR_UPDATES)}updateData(t,e,i,r,o,s,a=0){s||console.error("An attempt to use uninitialized data!"),this._glName||console.error("An attempt to update uninitialized texture!");const n=this._context.gl,l=this._descriptor,{pixelFormat:h,dataType:p,target:_,isImmutable:m}=l,u=l.internalFormat??this._deriveInternalFormat(h,p);if(m&&!this._wasImmutablyAllocated)throw new Error("Cannot update immutable texture before allocation!");const c=this._context.bindTexture(this,E.TEXTURE_UNIT_FOR_UPDATES,!0);if((e<0||i<0||r>l.width||o>l.height||e+r>l.width||i+o>l.height)&&console.error("An attempt to update out of bounds of the texture!"),this._configurePixelStorage(),a){if(!d(n))return void console.error("Webgl2 must be enabled to use dataRowOffset!");n.pixelStorei(n.UNPACK_SKIP_ROWS,a)}if(f(s)?d(n)?n.texSubImage2D(_,t,e,i,r,o,h,p,s):n.texSubImage2D(_,t,e,i,h,p,s):x(s)?n.compressedTexSubImage2D(_,t,e,i,r,o,u,s.levels[t]):n.texSubImage2D(_,t,e,i,r,o,h,p,s),a){if(!d(n))return void console.error("Webgl2 must be enabled to use dataRowOffset!");n.pixelStorei(n.UNPACK_SKIP_ROWS,0)}this._context.bindTexture(c,E.TEXTURE_UNIT_FOR_UPDATES)}updateData3D(t,e,i,r,o,s,a,n){n||console.error("An attempt to use uninitialized data!"),this._glName||console.error("An attempt to update uninitialized texture!");const l=this._context.gl;if(!d(l))throw new Error("3D textures are not supported in WebGL1");const h=this._descriptor,{pixelFormat:p,dataType:_,isImmutable:m,target:u}=h,c=h.internalFormat??this._deriveInternalFormat(p,_);if(m&&!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 T=this._context.bindTexture(this,E.TEXTURE_UNIT_FOR_UPDATES);if(this._context.setActiveTexture(E.TEXTURE_UNIT_FOR_UPDATES),(e<0||i<0||r<0||o>h.width||s>h.height||a>h.depth||e+o>h.width||i+s>h.height||r+a>h.depth)&&console.error("An attempt to update out of bounds of the texture!"),this._configurePixelStorage(),x(n))n=n.levels[t],l.compressedTexSubImage3D(u,t,e,i,r,o,s,a,c,n);else{const h=n;l.texSubImage3D(u,t,e,i,r,o,s,a,p,_,h)}this._context.bindTexture(T,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===a.LINEAR?(this._samplingModeDirty=!0,t.samplingMode=a.LINEAR_MIPMAP_NEAREST):t.samplingMode===a.NEAREST&&(this._samplingModeDirty=!0,t.samplingMode=a.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===o.WEBGL1)return t;switch(e){case h.FLOAT:switch(t){case p.RGBA:return _.RGBA32F;case p.RGB:return _.RGB32F;default:throw new Error("Unable to derive format")}case h.UNSIGNED_BYTE:switch(t){case p.RGBA:return _.RGBA8;case p.RGB:return _.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,i,r,o,s){const a=this._context.gl;if(!d(a))throw new Error("Immutable textures are not supported in WebGL1");if(!T(e))throw new Error("Immutable textures must have a sized internal format");if(!this._descriptor.isImmutable)return;const n=i?w(t,r,o,s):1;if(A(t)){if(null==s)throw new Error("Missing depth dimension for 3D texture upload");a.texStorage3D(t,n,e,r,o,s)}else a.texStorage2D(t,n,e,r,o);this._wasImmutablyAllocated=!0}_texImage(t,r,s,a,n,l,h){const p=this._context.gl;let _=null;const m=this._context.type===o.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,r,0,0,0,a,n,l,c,E,e)}else p.texSubImage2D(t,r,0,0,a,n,c,E,e)}}else{const e=i(h);if(d){if(null==l)throw new Error("Missing depth dimension for 3D texture upload");_.texImage3D(t,r,s,a,n,l,0,c,E,e)}else p.texImage2D(t,r,s,a,n,0,c,E,e)}else p.texImage2D(t,0,s,c,E,h)}_compressedTexImage(t,i,r,s,a,n,l){const h=this._context.gl;let p=null;const _=A(t),m=this._descriptor.isImmutable;if(_){if(this._context.type!==o.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,s,a,n,r,l)}else h.compressedTexSubImage2D(t,i,0,0,s,a,r,l)}else if(_){if(null==n)throw new Error("Missing depth dimension for 3D texture upload");p.compressedTexImage3D(t,i,r,s,a,n,0,l)}else h.compressedTexImage2D(t,i,r,s,a,0,l)}_forEachMipmapLevel(t,e=1/0){let{width:i,height:r,depth:o,hasMipmap:a,target:n}=this._descriptor;const l=n===s.TEXTURE_3D;if(null==i||null==r||l&&null==o)throw new Error("Missing texture dimensions for mipmap calculation");for(let s=0;t(s,i,r,o),a&&(1!==i||1!==r||l&&1!==o)&&!(s>=e);++s)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=d(e.gl),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!==n.CLAMP_TO_EDGE&&console.error("Non-power-of-two textures must have a wrap mode of CLAMP_TO_EDGE!"):i.wrapMode.s===n.CLAMP_TO_EDGE&&i.wrapMode.t===n.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===a.LINEAR_MIPMAP_NEAREST||i===a.LINEAR_MIPMAP_LINEAR?(i=a.LINEAR,e.hasMipmap||(r=a.LINEAR)):i!==a.NEAREST_MIPMAP_NEAREST&&i!==a.NEAREST_MIPMAP_LINEAR||(i=a.NEAREST,e.hasMipmap||(r=a.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 T(t){return t in _}function g(t){return t in m}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===s.TEXTURE_3D||t===s.TEXTURE_2D_ARRAY}function w(t,e,i,r=1){let o=Math.max(e,i);return t===s.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};