{"version":3,"file":"CompressedTextureResource.mjs","sources":["../../src/resources/CompressedTextureResource.ts"],"sourcesContent":["import { INTERNAL_FORMAT_TO_BYTES_PER_PIXEL } from '../const';\nimport { BlobResource } from './BlobResource';\n\nimport type { BaseTexture, GLTexture, Renderer } from 'pixijs/core';\nimport type { INTERNAL_FORMATS } from '../const';\n\n/**\n * Used in parseKTX\n * @ignore\n */\nexport type CompressedLevelBuffer = {\n    levelID: number,\n    levelWidth: number,\n    levelHeight: number,\n    levelBuffer: Uint8Array\n};\n\n/**\n * @ignore\n */\nexport interface ICompressedTextureResourceOptions\n{\n    format: INTERNAL_FORMATS;\n    width: number;\n    height: number;\n    levels?: number;\n    levelBuffers?: CompressedLevelBuffer[];\n}\n\n/**\n * Resource for compressed texture formats, as follows: S3TC/DXTn (& their sRGB formats), ATC, ASTC, ETC 1/2, PVRTC.\n *\n * Compressed textures improve performance when rendering is texture-bound. The texture data stays compressed in\n * graphics memory, increasing memory locality and speeding up texture fetches. These formats can also be used to store\n * more detail in the same amount of memory.\n *\n * For most developers, container file formats are a better abstraction instead of directly handling raw texture\n * data. PixiJS provides native support for the following texture file formats\n * (via {@link PIXI.loadBasis}, {@link PIXI.loadKTX}, and {@link PIXI.loadDDS}):\n *\n * **.dds** - the DirectDraw Surface file format stores DXTn (DXT-1,3,5) data. See {@link PIXI.parseDDS}\n * **.ktx** - the Khronos Texture Container file format supports storing all the supported WebGL compression formats.\n *  See {@link PIXI.parseKTX}.\n * **.basis** - the BASIS supercompressed file format stores texture data in an internal format that is transcoded\n *  to the compression format supported on the device at _runtime_. It also supports transcoding into a uncompressed\n *  format as a fallback; you must install the `pixijs/basis-loader`, `pixijs/basis-transcoder` packages separately to\n *  use these files. See {@link PIXI.BasisParser}.\n *\n * The loaders for the aforementioned formats use `CompressedTextureResource` internally. It is strongly suggested that\n * they be used instead.\n *\n * ## Working directly with CompressedTextureResource\n *\n * Since `CompressedTextureResource` inherits `BlobResource`, you can provide it a URL pointing to a file containing\n * the raw texture data (with no file headers!):\n * @example\n * import { CompressedTextureResource, INTERNAL_FORMATS } from 'pixijs/compressed-textures';\n * import { BaseTexture, Texture, ALPHA_MODES } from 'pixijs/browser';\n *\n * // The resource backing the texture data for your textures.\n * // NOTE: You can also provide a ArrayBufferView instead of a URL. This is used when loading data from a container file\n * //   format such as KTX, DDS, or BASIS.\n * const compressedResource = new CompressedTextureResource('bunny.dxt5', {\n *     format: INTERNAL_FORMATS.COMPRESSED_RGBA_S3TC_DXT5_EXT,\n *     width: 256,\n *     height: 256,\n * });\n *\n * // You can create a base-texture to the cache, so that future `Texture`s can be created using the `Texture.from` API.\n * const baseTexture = new BaseTexture(compressedResource, { pmaMode: ALPHA_MODES.NPM });\n *\n * // Create a Texture to add to the TextureCache\n * const texture = new Texture(baseTexture);\n *\n * // Add baseTexture & texture to the global texture cache\n * BaseTexture.addToCache(baseTexture, 'bunny.dxt5');\n * Texture.addToCache(texture, 'bunny.dxt5');\n * @memberof PIXI\n */\nexport class CompressedTextureResource extends BlobResource\n{\n    /** The compression format */\n    public format: INTERNAL_FORMATS;\n    /**\n     * The number of mipmap levels stored in the resource buffer.\n     * @default 1\n     */\n    public levels: number;\n\n    // Easy access to the WebGL extension providing support for the compression format via ContextSystem\n    private _extension: 's3tc' | 's3tc_sRGB' | 'atc' | 'astc' | 'etc' | 'etc1' | 'pvrtc';\n    // Buffer views for each mipmap level in the main buffer\n    private _levelBuffers: CompressedLevelBuffer[];\n\n    /**\n     * @param source - the buffer/URL holding the compressed texture data\n     * @param options\n     * @param {PIXI.INTERNAL_FORMATS} options.format - the compression format\n     * @param {number} options.width - the image width in pixels.\n     * @param {number} options.height - the image height in pixels.\n     * @param {number} [options.level=1] - the mipmap levels stored in the compressed texture, including level 0.\n     * @param {number} [options.levelBuffers] - the buffers for each mipmap level. `CompressedTextureResource` can allows you\n     *      to pass `null` for `source`, for cases where each level is stored in non-contiguous memory.\n     */\n    constructor(source: string | Uint8Array | Uint32Array, options: ICompressedTextureResourceOptions)\n    {\n        super(source, options);\n\n        this.format = options.format;\n        this.levels = options.levels || 1;\n\n        this._width = options.width;\n        this._height = options.height;\n\n        this._extension = CompressedTextureResource._formatToExtension(this.format);\n\n        if (options.levelBuffers || this.buffer)\n        {\n            // ViewableBuffer doesn't support byteOffset :-( so allow source to be Uint8Array\n            this._levelBuffers = options.levelBuffers\n                || CompressedTextureResource._createLevelBuffers(\n                    source instanceof Uint8Array ? source : this.buffer.uint8View,\n                    this.format,\n                    this.levels,\n                    4, 4, // PVRTC has 8x4 blocks in 2bpp mode\n                    this.width,\n                    this.height);\n        }\n    }\n\n    /**\n     * @override\n     * @param renderer - A reference to the current renderer\n     * @param _texture - the texture\n     * @param _glTexture - texture instance for this webgl context\n     */\n    upload(renderer: Renderer, _texture: BaseTexture, _glTexture: GLTexture): boolean\n    {\n        const gl = renderer.gl;\n        const extension = renderer.context.extensions[this._extension];\n\n        if (!extension)\n        {\n            throw new Error(`${this._extension} textures are not supported on the current machine`);\n        }\n        if (!this._levelBuffers)\n        {\n            // Do not try to upload data before BlobResource loads, unless the levelBuffers were provided directly!\n            return false;\n        }\n\n        for (let i = 0, j = this.levels; i < j; i++)\n        {\n            const { levelID, levelWidth, levelHeight, levelBuffer } = this._levelBuffers[i];\n\n            gl.compressedTexImage2D(gl.TEXTURE_2D, levelID, this.format, levelWidth, levelHeight, 0, levelBuffer);\n        }\n\n        return true;\n    }\n\n    /** @protected */\n    protected onBlobLoaded(): void\n    {\n        this._levelBuffers = CompressedTextureResource._createLevelBuffers(\n            this.buffer.uint8View,\n            this.format,\n            this.levels,\n            4, 4, // PVRTC has 8x4 blocks in 2bpp mode\n            this.width,\n            this.height);\n    }\n\n    /**\n     * Returns the key (to ContextSystem#extensions) for the WebGL extension supporting the compression format\n     * @private\n     * @param format - the compression format to get the extension for.\n     */\n    private static _formatToExtension(format: INTERNAL_FORMATS):\n    's3tc' | 's3tc_sRGB' | 'atc' |\n    'astc' | 'etc' | 'etc1' | 'pvrtc'\n    {\n        if (format >= 0x83F0 && format <= 0x83F3)\n        {\n            return 's3tc';\n        }\n        else if (format >= 0x9270 && format <= 0x9279)\n        {\n            return 'etc';\n        }\n        else if (format >= 0x8C00 && format <= 0x8C03)\n        {\n            return 'pvrtc';\n        }\n        else if (format >= 0x8D64)\n        {\n            return 'etc1';\n        }\n        else if (format >= 0x8C92 && format <= 0x87EE)\n        {\n            return 'atc';\n        }\n\n        throw new Error('Invalid (compressed) texture format given!');\n    }\n\n    /**\n     * Pre-creates buffer views for each mipmap level\n     * @private\n     * @param buffer -\n     * @param format - compression formats\n     * @param levels - mipmap levels\n     * @param blockWidth -\n     * @param blockHeight -\n     * @param imageWidth - width of the image in pixels\n     * @param imageHeight - height of the image in pixels\n     */\n    private static _createLevelBuffers(\n        buffer: Uint8Array,\n        format: INTERNAL_FORMATS,\n        levels: number,\n        blockWidth: number,\n        blockHeight: number,\n        imageWidth: number,\n        imageHeight: number\n    ): CompressedLevelBuffer[]\n    {\n        // The byte-size of the first level buffer\n        const buffers = new Array<CompressedLevelBuffer>(levels);\n\n        let offset = buffer.byteOffset;\n\n        let levelWidth = imageWidth;\n        let levelHeight = imageHeight;\n        let alignedLevelWidth = (levelWidth + blockWidth - 1) & ~(blockWidth - 1);\n        let alignedLevelHeight = (levelHeight + blockHeight - 1) & ~(blockHeight - 1);\n\n        let levelSize = alignedLevelWidth * alignedLevelHeight * INTERNAL_FORMAT_TO_BYTES_PER_PIXEL[format];\n\n        for (let i = 0; i < levels; i++)\n        {\n            buffers[i] = {\n                levelID: i,\n                levelWidth: levels > 1 ? levelWidth : alignedLevelWidth,\n                levelHeight: levels > 1 ? levelHeight : alignedLevelHeight,\n                levelBuffer: new Uint8Array(buffer.buffer, offset, levelSize)\n            };\n\n            offset += levelSize;\n\n            // Calculate levelBuffer dimensions for next iteration\n            levelWidth = (levelWidth >> 1) || 1;\n            levelHeight = (levelHeight >> 1) || 1;\n            alignedLevelWidth = (levelWidth + blockWidth - 1) & ~(blockWidth - 1);\n            alignedLevelHeight = (levelHeight + blockHeight - 1) & ~(blockHeight - 1);\n            levelSize = alignedLevelWidth * alignedLevelHeight * INTERNAL_FORMAT_TO_BYTES_PER_PIXEL[format];\n        }\n\n        return buffers;\n    }\n}\n"],"names":[],"mappings":"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"}