{"version":3,"file":"ExternalSource.mjs","sources":["../../../../../../src/rendering/renderers/shared/texture/sources/ExternalSource.ts"],"sourcesContent":["import { GlTexture } from '../../../gl/texture/GlTexture';\nimport { GPUTextureGpuData } from '../../../gpu/texture/GpuTextureSystem';\nimport { type Renderer, RendererType } from '../../../types';\nimport { TextureSource } from './TextureSource';\n\n// Shared placeholders - created lazily, reused by all ExternalSource instances\nconst placeholderGl: Record<number, WebGLTexture> = Object.create(null);\nconst placeholderGpu: Record<number, GPUTexture> = Object.create(null);\n\nfunction getPlaceholder(renderer: Renderer): GPUTexture | WebGLTexture\n{\n    if (renderer.type === RendererType.WEBGPU)\n    {\n        placeholderGpu[renderer.uid] ||= (renderer as any).gpu.device.createTexture({\n            label: 'ExternalSource placeholder',\n            size: { width: 1, height: 1 },\n            format: 'rgba8unorm',\n            usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n        });\n\n        return placeholderGpu[renderer.uid];\n    }\n\n    if (!placeholderGl[renderer.uid])\n    {\n        const gl = (renderer as any).gl as WebGLRenderingContext;\n        const texture = gl.createTexture();\n\n        gl.bindTexture(gl.TEXTURE_2D, texture);\n        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n\n        placeholderGl[renderer.uid] = texture;\n    }\n\n    return placeholderGl[renderer.uid];\n}\n\n/**\n * Options for creating an ExternalSource.\n * @category rendering\n * @advanced\n */\nexport interface ExternalSourceOptions\n{\n    /**\n     * The external GPU texture (GPUTexture for WebGPU, WebGLTexture for WebGL).\n     * If not provided, a shared 1x1 placeholder texture will be used until\n     * `updateGPUTexture()` is called.\n     * @advanced\n     */\n    resource?: GPUTexture | WebGLTexture;\n    /**\n     * The renderer this texture will be used with\n     * @advanced\n     */\n    renderer: Renderer;\n    /**\n     * Width of the texture. Auto-detected for GPUTexture, required for WebGLTexture.\n     * @advanced\n     */\n    width?: number;\n    /**\n     * Height of the texture. Auto-detected for GPUTexture, required for WebGLTexture.\n     * @advanced\n     */\n    height?: number;\n    /**\n     * Optional label for debugging\n     * @advanced\n     */\n    label?: string;\n}\n\n/**\n * A texture source that uses a GPU texture from an external library (e.g., Three.js).\n *\n * This allows sharing textures between PixiJS and other WebGL/WebGPU libraries without\n * re-uploading pixel data. The renderer is required so that ExternalSource can\n * pre-populate the GPU data and validate context ownership.\n * @example\n * ```typescript\n * // WebGPU - dimensions auto-detected\n * const texture = new Texture({\n *     source: new ExternalSource({\n *         resource: threeJsGpuTexture,\n *         renderer: renderer,\n *     })\n * });\n *\n * // WebGL - must provide dimensions (WebGLTexture is opaque)\n * const texture = new Texture({\n *     source: new ExternalSource({\n *         resource: threeJsGlTexture,\n *         renderer: renderer,\n *         width: 512,\n *         height: 512,\n *     })\n * });\n *\n * // Update to a new external texture\n * (texture.source as ExternalSource).updateGPUTexture(newExternalTexture);\n * ```\n * @category rendering\n * @advanced\n */\nexport class ExternalSource extends TextureSource<GPUTexture | WebGLTexture>\n{\n    private readonly _renderer: Renderer;\n\n    constructor({ resource, renderer, label, width, height }: ExternalSourceOptions)\n    {\n        resource ||= getPlaceholder(renderer);\n        width ||= width ?? (resource as GPUTexture)?.width ?? 1;\n        height ||= height ?? (resource as GPUTexture)?.height ?? 1;\n\n        // Only pass the minimal required options to TextureSource\n        super({\n            resource,\n            width,\n            height,\n            label,\n            // External textures shouldn't be garbage collected - the external library owns them\n            autoGarbageCollect: false,\n        });\n\n        this._renderer = renderer;\n\n        // Pre-populate _gpuData\n        this._initGpuData(resource);\n    }\n\n    /**\n     * Test if a resource is a valid external GPU texture.\n     * @param resource - The resource to test\n     * @returns True if the resource is a GPUTexture or WebGLTexture\n     */\n    public static test(resource: unknown): resource is GPUTexture | WebGLTexture\n    {\n        return (\n            (globalThis.GPUTexture && resource instanceof GPUTexture)\n            || (globalThis.WebGLTexture && resource instanceof WebGLTexture)\n        );\n    }\n\n    private _validateTexture(resource: GPUTexture | WebGLTexture): void\n    {\n        const renderer = this._renderer;\n        const isWebGPU = !!(renderer as any).gpu;\n        const isGPUTexture = globalThis.GPUTexture && resource instanceof GPUTexture;\n        const isWebGLTexture = globalThis.WebGLTexture && resource instanceof WebGLTexture;\n\n        if (isWebGPU && isWebGLTexture)\n        {\n            throw new Error('Cannot use WebGLTexture with a WebGPU renderer');\n        }\n\n        if (!isWebGPU && isGPUTexture)\n        {\n            throw new Error('Cannot use GPUTexture with a WebGL renderer');\n        }\n\n        // WebGL context ownership check\n        if (!isWebGPU)\n        {\n            const gl = (renderer as any).gl;\n\n            if (gl && !gl.isTexture(resource as WebGLTexture))\n            {\n                throw new Error('WebGLTexture does not belong to this renderer\\'s WebGL context');\n            }\n        }\n    }\n\n    private _initGpuData(resource: GPUTexture | WebGLTexture): void\n    {\n        const renderer = this._renderer;\n\n        this._validateTexture(resource);\n\n        if ((renderer as any).gpu)\n        {\n            // WebGPU\n            this._gpuData[renderer.uid] = new GPUTextureGpuData(resource as GPUTexture);\n        }\n        else\n        {\n            // WebGL\n            this._gpuData[renderer.uid] = new GlTexture(resource as WebGLTexture);\n        }\n    }\n\n    /**\n     * Update the external GPU texture reference.\n     * Call this when the external library provides a new texture.\n     * @param gpuTexture - The new GPU texture\n     * @param width - New width (required for WebGLTexture, auto-detected for GPUTexture)\n     * @param height - New height (required for WebGLTexture, auto-detected for GPUTexture)\n     */\n    public updateGPUTexture(gpuTexture: GPUTexture | WebGLTexture, width?: number, height?: number): void\n    {\n        const renderer = this._renderer;\n        const gpuData = this._gpuData[renderer.uid];\n\n        // Update the resource property to reflect the new texture\n        this.resource = gpuTexture;\n\n        if ((renderer as any).gpu)\n        {\n            // WebGPU - validate and update\n            this._validateTexture(gpuTexture);\n\n            const data = gpuData as GPUTextureGpuData;\n\n            if (data.gpuTexture !== gpuTexture)\n            {\n                data.gpuTexture = gpuTexture as GPUTexture;\n                data.textureView = null;\n\n                // Invalidate bind group hash\n                const textureSystem = (renderer as any).texture;\n\n                if (textureSystem?._bindGroupHash)\n                {\n                    textureSystem._bindGroupHash[this.uid] = null;\n                }\n            }\n\n            // Update dimensions from GPUTexture (or use provided values)\n            const newWidth = width ?? (gpuTexture as GPUTexture).width;\n            const newHeight = height ?? (gpuTexture as GPUTexture).height;\n\n            this.resize(newWidth, newHeight);\n        }\n        else\n        {\n            // WebGL - validate and update the texture reference\n            this._validateTexture(gpuTexture);\n\n            const data = gpuData as GlTexture;\n\n            data.texture = gpuTexture as WebGLTexture;\n\n            // WebGL: dimensions must be provided (WebGLTexture is opaque)\n            if (width !== undefined && height !== undefined)\n            {\n                this.resize(width, height);\n            }\n        }\n\n        this.emit('update', this);\n    }\n\n    public override destroy(): void\n    {\n        // Never destroy the GPU texture:\n        // - Placeholder is shared across all instances\n        // - External textures are owned by the external library\n        const renderer = this._renderer;\n\n        delete this._gpuData[renderer.uid];\n\n        super.destroy();\n    }\n}\n"],"names":[],"mappings":";;;;;;AAMA,MAAM,aAAA,mBAA8C,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA;AACtE,MAAM,cAAA,mBAA6C,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA;AAErE,SAAS,eAAe,QAAA,EACxB;AAVA,EAAA,IAAA,EAAA;AAWI,EAAA,IAAI,QAAA,CAAS,IAAA,KAAS,YAAA,CAAa,MAAA,EACnC;AACI,IAAA,cAAA,CAAA,EAAA,GAAe,SAAS,GAAA,CAAA,KAAxB,cAAA,CAAA,EAAA,CAAA,GAAkC,QAAA,CAAiB,GAAA,CAAI,OAAO,aAAA,CAAc;AAAA,MACxE,KAAA,EAAO,4BAAA;AAAA,MACP,IAAA,EAAM,EAAE,KAAA,EAAO,CAAA,EAAG,QAAQ,CAAA,EAAE;AAAA,MAC5B,MAAA,EAAQ,YAAA;AAAA,MACR,KAAA,EAAO,eAAA,CAAgB,eAAA,GAAkB,eAAA,CAAgB;AAAA,KAC5D,CAAA,CAAA;AAED,IAAA,OAAO,cAAA,CAAe,SAAS,GAAG,CAAA;AAAA,EACtC;AAEA,EAAA,IAAI,CAAC,aAAA,CAAc,QAAA,CAAS,GAAG,CAAA,EAC/B;AACI,IAAA,MAAM,KAAM,QAAA,CAAiB,EAAA;AAC7B,IAAA,MAAM,OAAA,GAAU,GAAG,aAAA,EAAc;AAEjC,IAAA,EAAA,CAAG,WAAA,CAAY,EAAA,CAAG,UAAA,EAAY,OAAO,CAAA;AACrC,IAAA,EAAA,CAAG,UAAA,CAAW,EAAA,CAAG,UAAA,EAAY,CAAA,EAAG,EAAA,CAAG,IAAA,EAAM,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,EAAA,CAAG,IAAA,EAAM,EAAA,CAAG,eAAe,IAAI,CAAA;AAEjF,IAAA,aAAA,CAAc,QAAA,CAAS,GAAG,CAAA,GAAI,OAAA;AAAA,EAClC;AAEA,EAAA,OAAO,aAAA,CAAc,SAAS,GAAG,CAAA;AACrC;AAsEO,MAAM,uBAAuB,aAAA,CACpC;AAAA,EAGI,YAAY,EAAE,QAAA,EAAU,UAAU,KAAA,EAAO,KAAA,EAAO,QAAO,EACvD;AACI,IAAA,QAAA,KAAA,QAAA,GAAa,eAAe,QAAQ,CAAA,CAAA;AACpC,IAAA,KAAA,KAAA,KAAA,GAAU,KAAA,IAAU,UAAyB,KAAA,IAAS,CAAA,CAAA;AACtD,IAAA,MAAA,KAAA,MAAA,GAAW,MAAA,IAAW,UAAyB,MAAA,IAAU,CAAA,CAAA;AAGzD,IAAA,KAAA,CAAM;AAAA,MACF,QAAA;AAAA,MACA,KAAA;AAAA,MACA,MAAA;AAAA,MACA,KAAA;AAAA;AAAA,MAEA,kBAAA,EAAoB;AAAA,KACvB,CAAA;AAED,IAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AAGjB,IAAA,IAAA,CAAK,aAAa,QAAQ,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,KAAK,QAAA,EACnB;AACI,IAAA,OACK,WAAW,UAAA,IAAc,QAAA,YAAoB,UAAA,IAC1C,UAAA,CAAW,gBAAgB,QAAA,YAAoB,YAAA;AAAA,EAE3D;AAAA,EAEQ,iBAAiB,QAAA,EACzB;AACI,IAAA,MAAM,WAAW,IAAA,CAAK,SAAA;AACtB,IAAA,MAAM,QAAA,GAAW,CAAC,CAAE,QAAA,CAAiB,GAAA;AACrC,IAAA,MAAM,YAAA,GAAe,UAAA,CAAW,UAAA,IAAc,QAAA,YAAoB,UAAA;AAClE,IAAA,MAAM,cAAA,GAAiB,UAAA,CAAW,YAAA,IAAgB,QAAA,YAAoB,YAAA;AAEtE,IAAA,IAAI,YAAY,cAAA,EAChB;AACI,MAAA,MAAM,IAAI,MAAM,gDAAgD,CAAA;AAAA,IACpE;AAEA,IAAA,IAAI,CAAC,YAAY,YAAA,EACjB;AACI,MAAA,MAAM,IAAI,MAAM,6CAA6C,CAAA;AAAA,IACjE;AAGA,IAAA,IAAI,CAAC,QAAA,EACL;AACI,MAAA,MAAM,KAAM,QAAA,CAAiB,EAAA;AAE7B,MAAA,IAAI,EAAA,IAAM,CAAC,EAAA,CAAG,SAAA,CAAU,QAAwB,CAAA,EAChD;AACI,QAAA,MAAM,IAAI,MAAM,+DAAgE,CAAA;AAAA,MACpF;AAAA,IACJ;AAAA,EACJ;AAAA,EAEQ,aAAa,QAAA,EACrB;AACI,IAAA,MAAM,WAAW,IAAA,CAAK,SAAA;AAEtB,IAAA,IAAA,CAAK,iBAAiB,QAAQ,CAAA;AAE9B,IAAA,IAAK,SAAiB,GAAA,EACtB;AAEI,MAAA,IAAA,CAAK,SAAS,QAAA,CAAS,GAAG,CAAA,GAAI,IAAI,kBAAkB,QAAsB,CAAA;AAAA,IAC9E,CAAA,MAEA;AAEI,MAAA,IAAA,CAAK,SAAS,QAAA,CAAS,GAAG,CAAA,GAAI,IAAI,UAAU,QAAwB,CAAA;AAAA,IACxE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,gBAAA,CAAiB,UAAA,EAAuC,KAAA,EAAgB,MAAA,EAC/E;AACI,IAAA,MAAM,WAAW,IAAA,CAAK,SAAA;AACtB,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,QAAA,CAAS,QAAA,CAAS,GAAG,CAAA;AAG1C,IAAA,IAAA,CAAK,QAAA,GAAW,UAAA;AAEhB,IAAA,IAAK,SAAiB,GAAA,EACtB;AAEI,MAAA,IAAA,CAAK,iBAAiB,UAAU,CAAA;AAEhC,MAAA,MAAM,IAAA,GAAO,OAAA;AAEb,MAAA,IAAI,IAAA,CAAK,eAAe,UAAA,EACxB;AACI,QAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAClB,QAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AAGnB,QAAA,MAAM,gBAAiB,QAAA,CAAiB,OAAA;AAExC,QAAA,IAAI,eAAe,cAAA,EACnB;AACI,UAAA,aAAA,CAAc,cAAA,CAAe,IAAA,CAAK,GAAG,CAAA,GAAI,IAAA;AAAA,QAC7C;AAAA,MACJ;AAGA,MAAA,MAAM,QAAA,GAAW,SAAU,UAAA,CAA0B,KAAA;AACrD,MAAA,MAAM,SAAA,GAAY,UAAW,UAAA,CAA0B,MAAA;AAEvD,MAAA,IAAA,CAAK,MAAA,CAAO,UAAU,SAAS,CAAA;AAAA,IACnC,CAAA,MAEA;AAEI,MAAA,IAAA,CAAK,iBAAiB,UAAU,CAAA;AAEhC,MAAA,MAAM,IAAA,GAAO,OAAA;AAEb,MAAA,IAAA,CAAK,OAAA,GAAU,UAAA;AAGf,MAAA,IAAI,KAAA,KAAU,KAAA,CAAA,IAAa,MAAA,KAAW,KAAA,CAAA,EACtC;AACI,QAAA,IAAA,CAAK,MAAA,CAAO,OAAO,MAAM,CAAA;AAAA,MAC7B;AAAA,IACJ;AAEA,IAAA,IAAA,CAAK,IAAA,CAAK,UAAU,IAAI,CAAA;AAAA,EAC5B;AAAA,EAEgB,OAAA,GAChB;AAII,IAAA,MAAM,WAAW,IAAA,CAAK,SAAA;AAEtB,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,QAAA,CAAS,GAAG,CAAA;AAEjC,IAAA,KAAA,CAAM,OAAA,EAAQ;AAAA,EAClB;AACJ;;;;"}