UNPKG

21.2 kBSource Map (JSON)View Raw
1{"version":3,"file":"TextureSystem.js","sources":["../../src/textures/TextureSystem.ts"],"sourcesContent":["import { MIPMAP_MODES, SAMPLER_TYPES, SCALE_MODES, TYPES, WRAP_MODES } from '@pixi/constants';\nimport { extensions, ExtensionType } from '@pixi/extensions';\nimport { removeItems } from '@pixi/utils';\nimport { BaseTexture } from './BaseTexture';\nimport { GLTexture } from './GLTexture';\nimport { mapInternalFormatToSamplerType } from './utils/mapInternalFormatToSamplerType';\nimport { mapTypeAndFormatToInternalFormat } from './utils/mapTypeAndFormatToInternalFormat';\n\nimport type { ExtensionMetadata } from '@pixi/extensions';\nimport type { IRenderingContext } from '../IRenderer';\nimport type { Renderer } from '../Renderer';\nimport type { ISystem } from '../system/ISystem';\nimport type { Texture } from './Texture';\n\n/**\n * System plugin to the renderer to manage textures.\n * @memberof PIXI\n */\nexport class TextureSystem implements ISystem\n{\n /** @ignore */\n static extension: ExtensionMetadata = {\n type: ExtensionType.RendererSystem,\n name: 'texture',\n };\n\n /**\n * Bound textures.\n * @readonly\n */\n public boundTextures: BaseTexture[];\n\n /**\n * List of managed textures.\n * @readonly\n */\n public managedTextures: Array<BaseTexture>;\n\n /** Whether glTexture with int/uint sampler type was uploaded. */\n protected hasIntegerTextures: boolean;\n protected CONTEXT_UID: number;\n protected gl: IRenderingContext;\n protected internalFormats: { [type: number]: { [format: number]: number } };\n protected samplerTypes: Record<number, SAMPLER_TYPES>;\n protected webGLVersion: number;\n\n /**\n * BaseTexture value that shows that we don't know what is bound.\n * @readonly\n */\n protected unknownTexture: BaseTexture;\n\n /**\n * Did someone temper with textures state? We'll overwrite them when we need to unbind something.\n * @private\n */\n protected _unknownBoundTextures: boolean;\n\n /**\n * Current location.\n * @readonly\n */\n currentLocation: number;\n emptyTextures: {[key: number]: GLTexture};\n private renderer: Renderer;\n\n /**\n * @param renderer - The renderer this system works for.\n */\n constructor(renderer: Renderer)\n {\n this.renderer = renderer;\n\n // TODO set to max textures...\n this.boundTextures = [];\n this.currentLocation = -1;\n this.managedTextures = [];\n\n this._unknownBoundTextures = false;\n this.unknownTexture = new BaseTexture();\n\n this.hasIntegerTextures = false;\n }\n\n /** Sets up the renderer context and necessary buffers. */\n contextChange(): void\n {\n const gl = this.gl = this.renderer.gl;\n\n this.CONTEXT_UID = this.renderer.CONTEXT_UID;\n\n this.webGLVersion = this.renderer.context.webGLVersion;\n\n this.internalFormats = mapTypeAndFormatToInternalFormat(gl);\n this.samplerTypes = mapInternalFormatToSamplerType(gl);\n\n const maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);\n\n this.boundTextures.length = maxTextures;\n\n for (let i = 0; i < maxTextures; i++)\n {\n this.boundTextures[i] = null;\n }\n\n // TODO move this.. to a nice make empty textures class..\n this.emptyTextures = {};\n\n const emptyTexture2D = new GLTexture(gl.createTexture());\n\n gl.bindTexture(gl.TEXTURE_2D, emptyTexture2D.texture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));\n\n this.emptyTextures[gl.TEXTURE_2D] = emptyTexture2D;\n this.emptyTextures[gl.TEXTURE_CUBE_MAP] = new GLTexture(gl.createTexture());\n\n gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.emptyTextures[gl.TEXTURE_CUBE_MAP].texture);\n\n for (let i = 0; i < 6; i++)\n {\n gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n }\n\n gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n\n for (let i = 0; i < this.boundTextures.length; i++)\n {\n this.bind(null, i);\n }\n }\n\n /**\n * Bind a texture to a specific location\n *\n * If you want to unbind something, please use `unbind(texture)` instead of `bind(null, textureLocation)`\n * @param texture - Texture to bind\n * @param [location=0] - Location to bind at\n */\n bind(texture: Texture | BaseTexture, location = 0): void\n {\n const { gl } = this;\n\n texture = texture?.castToBaseTexture();\n\n // cannot bind partial texture\n // TODO: report a warning\n if (texture?.valid && !texture.parentTextureArray)\n {\n texture.touched = this.renderer.textureGC.count;\n\n const glTexture = texture._glTextures[this.CONTEXT_UID] || this.initTexture(texture);\n\n if (this.boundTextures[location] !== texture)\n {\n if (this.currentLocation !== location)\n {\n this.currentLocation = location;\n gl.activeTexture(gl.TEXTURE0 + location);\n }\n\n gl.bindTexture(texture.target, glTexture.texture);\n }\n\n if (glTexture.dirtyId !== texture.dirtyId)\n {\n if (this.currentLocation !== location)\n {\n this.currentLocation = location;\n gl.activeTexture(gl.TEXTURE0 + location);\n }\n this.updateTexture(texture);\n }\n else if (glTexture.dirtyStyleId !== texture.dirtyStyleId)\n {\n this.updateTextureStyle(texture);\n }\n\n this.boundTextures[location] = texture;\n }\n else\n {\n if (this.currentLocation !== location)\n {\n this.currentLocation = location;\n gl.activeTexture(gl.TEXTURE0 + location);\n }\n\n gl.bindTexture(gl.TEXTURE_2D, this.emptyTextures[gl.TEXTURE_2D].texture);\n this.boundTextures[location] = null;\n }\n }\n\n /** Resets texture location and bound textures Actual `bind(null, i)` calls will be performed at next `unbind()` call */\n reset(): void\n {\n this._unknownBoundTextures = true;\n this.hasIntegerTextures = false;\n this.currentLocation = -1;\n\n for (let i = 0; i < this.boundTextures.length; i++)\n {\n this.boundTextures[i] = this.unknownTexture;\n }\n }\n\n /**\n * Unbind a texture.\n * @param texture - Texture to bind\n */\n unbind(texture?: BaseTexture): void\n {\n const { gl, boundTextures } = this;\n\n if (this._unknownBoundTextures)\n {\n this._unknownBoundTextures = false;\n // someone changed webGL state,\n // we have to be sure that our texture does not appear in multi-texture renderer samplers\n for (let i = 0; i < boundTextures.length; i++)\n {\n if (boundTextures[i] === this.unknownTexture)\n {\n this.bind(null, i);\n }\n }\n }\n\n for (let i = 0; i < boundTextures.length; i++)\n {\n if (boundTextures[i] === texture)\n {\n if (this.currentLocation !== i)\n {\n gl.activeTexture(gl.TEXTURE0 + i);\n this.currentLocation = i;\n }\n\n gl.bindTexture(texture.target, this.emptyTextures[texture.target].texture);\n boundTextures[i] = null;\n }\n }\n }\n\n /**\n * Ensures that current boundTextures all have FLOAT sampler type,\n * see {@link PIXI.SAMPLER_TYPES} for explanation.\n * @param maxTextures - number of locations to check\n */\n ensureSamplerType(maxTextures: number): void\n {\n const { boundTextures, hasIntegerTextures, CONTEXT_UID } = this;\n\n if (!hasIntegerTextures)\n {\n return;\n }\n\n for (let i = maxTextures - 1; i >= 0; --i)\n {\n const tex = boundTextures[i];\n\n if (tex)\n {\n const glTexture = tex._glTextures[CONTEXT_UID];\n\n if (glTexture.samplerType !== SAMPLER_TYPES.FLOAT)\n {\n this.renderer.texture.unbind(tex);\n }\n }\n }\n }\n\n /**\n * Initialize a texture\n * @private\n * @param texture - Texture to initialize\n */\n initTexture(texture: BaseTexture): GLTexture\n {\n const glTexture = new GLTexture(this.gl.createTexture());\n\n // guarantee an update..\n glTexture.dirtyId = -1;\n\n texture._glTextures[this.CONTEXT_UID] = glTexture;\n\n this.managedTextures.push(texture);\n texture.on('dispose', this.destroyTexture, this);\n\n return glTexture;\n }\n\n initTextureType(texture: BaseTexture, glTexture: GLTexture): void\n {\n glTexture.internalFormat = this.internalFormats[texture.type]?.[texture.format] ?? texture.format;\n glTexture.samplerType = this.samplerTypes[glTexture.internalFormat] ?? SAMPLER_TYPES.FLOAT;\n\n if (this.webGLVersion === 2 && texture.type === TYPES.HALF_FLOAT)\n {\n // TYPES.HALF_FLOAT is WebGL1 HALF_FLOAT_OES\n // we have to convert it to WebGL HALF_FLOAT\n glTexture.type = this.gl.HALF_FLOAT;\n }\n else\n {\n glTexture.type = texture.type;\n }\n }\n\n /**\n * Update a texture\n * @private\n * @param {PIXI.BaseTexture} texture - Texture to initialize\n */\n updateTexture(texture: BaseTexture): void\n {\n const glTexture = texture._glTextures[this.CONTEXT_UID];\n\n if (!glTexture)\n {\n return;\n }\n\n const renderer = this.renderer;\n\n this.initTextureType(texture, glTexture);\n\n if (texture.resource?.upload(renderer, texture, glTexture))\n {\n // texture is uploaded, dont do anything!\n if (glTexture.samplerType !== SAMPLER_TYPES.FLOAT)\n {\n this.hasIntegerTextures = true;\n }\n }\n else\n {\n // default, renderTexture-like logic\n const width = texture.realWidth;\n const height = texture.realHeight;\n const gl = renderer.gl;\n\n if (glTexture.width !== width\n || glTexture.height !== height\n || glTexture.dirtyId < 0)\n {\n glTexture.width = width;\n glTexture.height = height;\n\n gl.texImage2D(texture.target, 0,\n glTexture.internalFormat,\n width,\n height,\n 0,\n texture.format,\n glTexture.type,\n null);\n }\n }\n\n // lets only update what changes..\n if (texture.dirtyStyleId !== glTexture.dirtyStyleId)\n {\n this.updateTextureStyle(texture);\n }\n glTexture.dirtyId = texture.dirtyId;\n }\n\n /**\n * Deletes the texture from WebGL\n * @private\n * @param texture - the texture to destroy\n * @param [skipRemove=false] - Whether to skip removing the texture from the TextureManager.\n */\n destroyTexture(texture: BaseTexture | Texture, skipRemove?: boolean): void\n {\n const { gl } = this;\n\n texture = texture.castToBaseTexture();\n\n if (texture._glTextures[this.CONTEXT_UID])\n {\n this.unbind(texture);\n\n gl.deleteTexture(texture._glTextures[this.CONTEXT_UID].texture);\n texture.off('dispose', this.destroyTexture, this);\n\n delete texture._glTextures[this.CONTEXT_UID];\n\n if (!skipRemove)\n {\n const i = this.managedTextures.indexOf(texture);\n\n if (i !== -1)\n {\n removeItems(this.managedTextures, i, 1);\n }\n }\n }\n }\n\n /**\n * Update texture style such as mipmap flag\n * @private\n * @param {PIXI.BaseTexture} texture - Texture to update\n */\n updateTextureStyle(texture: BaseTexture): void\n {\n const glTexture = texture._glTextures[this.CONTEXT_UID];\n\n if (!glTexture)\n {\n return;\n }\n\n if ((texture.mipmap === MIPMAP_MODES.POW2 || this.webGLVersion !== 2) && !texture.isPowerOfTwo)\n {\n glTexture.mipmap = false;\n }\n else\n {\n glTexture.mipmap = texture.mipmap >= 1;\n }\n\n if (this.webGLVersion !== 2 && !texture.isPowerOfTwo)\n {\n glTexture.wrapMode = WRAP_MODES.CLAMP;\n }\n else\n {\n glTexture.wrapMode = texture.wrapMode;\n }\n\n if (texture.resource?.style(this.renderer, texture, glTexture))\n {\n // style is set, dont do anything!\n }\n else\n {\n this.setStyle(texture, glTexture);\n }\n\n glTexture.dirtyStyleId = texture.dirtyStyleId;\n }\n\n /**\n * Set style for texture\n * @private\n * @param texture - Texture to update\n * @param glTexture\n */\n setStyle(texture: BaseTexture, glTexture: GLTexture): void\n {\n const gl = this.gl;\n\n if (glTexture.mipmap && texture.mipmap !== MIPMAP_MODES.ON_MANUAL)\n {\n gl.generateMipmap(texture.target);\n }\n\n gl.texParameteri(texture.target, gl.TEXTURE_WRAP_S, glTexture.wrapMode);\n gl.texParameteri(texture.target, gl.TEXTURE_WRAP_T, glTexture.wrapMode);\n\n if (glTexture.mipmap)\n {\n /* eslint-disable max-len */\n gl.texParameteri(texture.target, gl.TEXTURE_MIN_FILTER, texture.scaleMode === SCALE_MODES.LINEAR ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST);\n /* eslint-disable max-len */\n\n const anisotropicExt = this.renderer.context.extensions.anisotropicFiltering;\n\n if (anisotropicExt && texture.anisotropicLevel > 0 && texture.scaleMode === SCALE_MODES.LINEAR)\n {\n const level = Math.min(texture.anisotropicLevel, gl.getParameter(anisotropicExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT));\n\n gl.texParameterf(texture.target, anisotropicExt.TEXTURE_MAX_ANISOTROPY_EXT, level);\n }\n }\n else\n {\n gl.texParameteri(texture.target, gl.TEXTURE_MIN_FILTER, texture.scaleMode === SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST);\n }\n\n gl.texParameteri(texture.target, gl.TEXTURE_MAG_FILTER, texture.scaleMode === SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST);\n }\n\n destroy(): void\n {\n this.renderer = null;\n }\n}\n\nextensions.add(TextureSystem);\n"],"names":["BaseTexture","mapTypeAndFormatToInternalFormat","mapInternalFormatToSamplerType","GLTexture","SAMPLER_TYPES","TYPES","removeItems","MIPMAP_MODES","WRAP_MODES","SCALE_MODES","ExtensionType","extensions"],"mappings":"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"}
\No newline at end of file