{"version":3,"file":"StencilMaskPipe.mjs","sources":["../../../../src/rendering/mask/stencil/StencilMaskPipe.ts"],"sourcesContent":["import { ExtensionType } from '../../../extensions/Extensions';\nimport { CLEAR } from '../../renderers/gl/const';\nimport { STENCIL_MODES } from '../../renderers/shared/state/const';\n\nimport type { Container } from '../../../scene/container/Container';\nimport type { Effect } from '../../../scene/container/Effect';\nimport type { WebGLRenderer } from '../../renderers/gl/WebGLRenderer';\nimport type { WebGPURenderer } from '../../renderers/gpu/WebGPURenderer';\nimport type { InstructionSet } from '../../renderers/shared/instructions/InstructionSet';\nimport type { InstructionPipe } from '../../renderers/shared/instructions/RenderPipe';\nimport type { Renderable } from '../../renderers/shared/Renderable';\nimport type { Renderer } from '../../renderers/types';\nimport type { StencilMask } from './StencilMask';\nimport type { StencilMaskInstruction } from './StencilMaskTypes';\n\n/** @internal */\nexport class StencilMaskPipe implements InstructionPipe<StencilMaskInstruction>\n{\n    public static extension = {\n        type: [\n            ExtensionType.WebGLPipes,\n            ExtensionType.WebGPUPipes,\n        ],\n        name: 'stencilMask',\n    } as const;\n\n    private _renderer: Renderer;\n\n    // used when building and also when executing..\n    private _maskStackHash: Record<number, number> = {};\n\n    private _maskHash = new WeakMap<StencilMask, {\n        instructionsStart: number,\n        instructionsLength: number,\n    }>();\n\n    constructor(renderer: Renderer)\n    {\n        this._renderer = renderer;\n    }\n\n    public push(mask: Effect, _container: Container, instructionSet: InstructionSet): void\n    {\n        const effect = mask as StencilMask;\n\n        const renderer = this._renderer;\n\n        renderer.renderPipes.batch.break(instructionSet);\n\n        renderer.renderPipes.blendMode.setBlendMode(effect.mask as Renderable, 'none', instructionSet);\n\n        instructionSet.add({\n            renderPipeId: 'stencilMask',\n            action: 'pushMaskBegin',\n            mask,\n            inverse: _container._maskOptions.inverse,\n            canBundle: false,\n        } as StencilMaskInstruction);\n\n        const maskContainer = effect.mask;\n\n        maskContainer.includeInBuild = true;\n\n        if (!this._maskHash.has(effect))\n        {\n            this._maskHash.set(effect, {\n                instructionsStart: 0,\n                instructionsLength: 0,\n            });\n        }\n\n        const maskData = this._maskHash.get(effect);\n\n        maskData.instructionsStart = instructionSet.instructionSize;\n\n        maskContainer.collectRenderables(\n            instructionSet,\n            renderer,\n            null\n        );\n\n        maskContainer.includeInBuild = false;\n\n        renderer.renderPipes.batch.break(instructionSet);\n\n        instructionSet.add({\n            renderPipeId: 'stencilMask',\n            action: 'pushMaskEnd',\n            mask,\n            inverse: _container._maskOptions.inverse,\n            canBundle: false,\n        } as StencilMaskInstruction);\n\n        const instructionsLength = instructionSet.instructionSize - maskData.instructionsStart - 1;\n\n        maskData.instructionsLength = instructionsLength;\n\n        const renderTargetUid = renderer.renderTarget.renderTarget.uid;\n\n        this._maskStackHash[renderTargetUid] ??= 0;\n    }\n\n    public pop(mask: Effect, _container: Container, instructionSet: InstructionSet): void\n    {\n        const effect = mask as StencilMask;\n\n        const renderer = this._renderer;\n\n        // stencil is stored based on current render target..\n        renderer.renderPipes.batch.break(instructionSet);\n        renderer.renderPipes.blendMode.setBlendMode(effect.mask as Renderable, 'none', instructionSet);\n\n        instructionSet.add({\n            renderPipeId: 'stencilMask',\n            action: 'popMaskBegin',\n            inverse: _container._maskOptions.inverse,\n            canBundle: false,\n        } as StencilMaskInstruction);\n\n        const maskData = this._maskHash.get(mask as StencilMask);\n\n        for (let i = 0; i < maskData.instructionsLength; i++)\n        {\n            // eslint-disable-next-line max-len\n            instructionSet.instructions[instructionSet.instructionSize++] = instructionSet.instructions[maskData.instructionsStart++];\n        }\n\n        instructionSet.add({\n            renderPipeId: 'stencilMask',\n            action: 'popMaskEnd',\n            canBundle: false,\n        });\n    }\n\n    public execute(instruction: StencilMaskInstruction)\n    {\n        const renderer = this._renderer;\n\n        const gpuRenderer = renderer as WebGLRenderer | WebGPURenderer;\n        const renderTargetUid = renderer.renderTarget.renderTarget.uid;\n\n        let maskStackIndex = this._maskStackHash[renderTargetUid] ??= 0;\n\n        if (instruction.action === 'pushMaskBegin')\n        {\n            // we create the depth and stencil buffers JIT\n            // as no point allocating the memory if we don't use it\n            gpuRenderer.renderTarget.ensureDepthStencil();\n\n            gpuRenderer.stencil.setStencilMode(STENCIL_MODES.RENDERING_MASK_ADD, maskStackIndex);\n\n            maskStackIndex++;\n\n            gpuRenderer.colorMask.setMask(0);\n        }\n        else if (instruction.action === 'pushMaskEnd')\n        {\n            if (instruction.inverse)\n            {\n                gpuRenderer.stencil.setStencilMode(STENCIL_MODES.INVERSE_MASK_ACTIVE, maskStackIndex);\n            }\n            else\n            {\n                gpuRenderer.stencil.setStencilMode(STENCIL_MODES.MASK_ACTIVE, maskStackIndex);\n            }\n\n            gpuRenderer.colorMask.setMask(0xF);\n        }\n        else if (instruction.action === 'popMaskBegin')\n        {\n            gpuRenderer.colorMask.setMask(0);\n\n            if (maskStackIndex !== 0)\n            {\n                gpuRenderer.stencil.setStencilMode(STENCIL_MODES.RENDERING_MASK_REMOVE, maskStackIndex);\n            }\n            else\n            {\n                gpuRenderer.renderTarget.clear(null, CLEAR.STENCIL);\n                gpuRenderer.stencil.setStencilMode(STENCIL_MODES.DISABLED, maskStackIndex);\n            }\n\n            maskStackIndex--;\n        }\n        else if (instruction.action === 'popMaskEnd')\n        {\n            if (instruction.inverse)\n            {\n                gpuRenderer.stencil.setStencilMode(STENCIL_MODES.INVERSE_MASK_ACTIVE, maskStackIndex);\n            }\n            else\n            {\n                gpuRenderer.stencil.setStencilMode(STENCIL_MODES.MASK_ACTIVE, maskStackIndex);\n            }\n\n            gpuRenderer.colorMask.setMask(0xF);\n        }\n\n        this._maskStackHash[renderTargetUid] = maskStackIndex;\n    }\n\n    public destroy()\n    {\n        this._renderer = null;\n        this._maskStackHash = null;\n        this._maskHash = null;\n    }\n}\n"],"names":[],"mappings":"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"}