{"version":3,"file":"StencilMaskPipe.mjs","sources":["../../../../src/rendering/mask/stencil/StencilMaskPipe.ts"],"sourcesContent":["import { ExtensionType } from '../../../extensions/Extensions';\nimport { collectAllRenderables } from '../../../scene/container/utils/buildInstructions';\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 { Instruction } from '../../renderers/shared/instructions/Instruction';\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';\n\ntype MaskMode = 'pushMaskBegin' | 'pushMaskEnd' | 'popMaskBegin' | 'popMaskEnd';\n\nexport interface StencilMaskInstruction extends Instruction\n{\n    renderPipeId: 'stencilMask',\n    action: MaskMode,\n    mask: StencilMask,\n}\n\nexport class StencilMaskPipe implements InstructionPipe<StencilMaskInstruction>\n{\n    public static extension = {\n        type: [\n            ExtensionType.WebGLPipes,\n            ExtensionType.WebGPUPipes,\n            ExtensionType.CanvasPipes,\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            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        collectAllRenderables(\n            maskContainer,\n            instructionSet,\n            renderer,\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            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            canBundle: false,\n        });\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        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            renderer.renderTarget.ensureDepthStencil();\n\n            renderer.stencil.setStencilMode(STENCIL_MODES.RENDERING_MASK_ADD, maskStackIndex);\n\n            maskStackIndex++;\n\n            renderer.colorMask.setMask(0);\n        }\n        else if (instruction.action === 'pushMaskEnd')\n        {\n            renderer.stencil.setStencilMode(STENCIL_MODES.MASK_ACTIVE, maskStackIndex);\n            renderer.colorMask.setMask(0xF);\n        }\n        else if (instruction.action === 'popMaskBegin')\n        {\n            renderer.colorMask.setMask(0);\n\n            if (maskStackIndex !== 0)\n            {\n                renderer.stencil.setStencilMode(STENCIL_MODES.RENDERING_MASK_REMOVE, maskStackIndex);\n            }\n            else\n            {\n                renderer.renderTarget.clear(null, CLEAR.STENCIL);\n                renderer.stencil.setStencilMode(STENCIL_MODES.DISABLED, maskStackIndex);\n            }\n\n            maskStackIndex--;\n        }\n        else if (instruction.action === 'popMaskEnd')\n        {\n            renderer.stencil.setStencilMode(STENCIL_MODES.MASK_ACTIVE, maskStackIndex);\n\n            renderer.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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"}