{"version":3,"file":"RenderTextureSystem.mjs","sources":["../../src/renderTexture/RenderTextureSystem.ts"],"sourcesContent":["import { Color } from '@pixi/color';\nimport { extensions, ExtensionType } from '@pixi/extensions';\nimport { Rectangle } from '@pixi/math';\n\nimport type { ColorSource } from '@pixi/color';\nimport type { BUFFER_BITS } from '@pixi/constants';\nimport type { ExtensionMetadata } from '@pixi/extensions';\nimport type { ISize } from '@pixi/math';\nimport type { MaskData } from '../mask/MaskData';\nimport type { Renderer } from '../Renderer';\nimport type { ISystem } from '../system/ISystem';\nimport type { BaseRenderTexture } from './BaseRenderTexture';\nimport type { RenderTexture } from './RenderTexture';\n\n// Temporary rectangle for assigned sourceFrame or destinationFrame\nconst tempRect = new Rectangle();\n\n// Temporary rectangle for renderTexture destinationFrame\nconst tempRect2 = new Rectangle();\n\n/* eslint-disable max-len */\n/**\n * System plugin to the renderer to manage render textures.\n *\n * Should be added after FramebufferSystem\n *\n * ### Frames\n *\n * The `RenderTextureSystem` holds a sourceFrame → destinationFrame projection. The following table explains the different\n * coordinate spaces used:\n *\n * | Frame                  | Description                                                      | Coordinate System                                       |\n * | ---------------------- | ---------------------------------------------------------------- | ------------------------------------------------------- |\n * | sourceFrame            | The rectangle inside of which display-objects are being rendered | **World Space**: The origin on the top-left             |\n * | destinationFrame       | The rectangle in the render-target (canvas or texture) into which contents should be rendered | If rendering to the canvas, this is in screen space and the origin is on the top-left. If rendering to a render-texture, this is in its base-texture's space with the origin on the bottom-left.  |\n * | viewportFrame          | The framebuffer viewport corresponding to the destination-frame  | **Window Coordinates**: The origin is always on the bottom-left. |\n * @memberof PIXI\n */\nexport class RenderTextureSystem implements ISystem\n{\n    /** @ignore */\n    static extension: ExtensionMetadata = {\n        type: ExtensionType.RendererSystem,\n        name: 'renderTexture',\n    };\n\n    /* eslint-enable max-len */\n\n    /**\n     * List of masks for the {@link PIXI.StencilSystem}.\n     * @readonly\n     */\n    public defaultMaskStack: Array<MaskData>;\n\n    /**\n     * Render texture currently bound. {@code null} if rendering to the canvas.\n     * @readonly\n     */\n    public current: RenderTexture | null;\n\n    /**\n     * The source frame for the render-target's projection mapping.\n     *\n     * See {@link PIXI.ProjectionSystem#sourceFrame} for more details\n     */\n    public readonly sourceFrame: Rectangle;\n\n    /**\n     * The destination frame for the render-target's projection mapping.\n     *\n     * See {@link PIXI.ProjectionSystem#destinationFrame} for more details.\n     */\n    public readonly destinationFrame: Rectangle;\n\n    /**\n     * The viewport frame for the render-target's viewport binding. This is equal to the destination-frame\n     * for render-textures, while it is y-flipped when rendering to the screen (i.e. its origin is always on\n     * the bottom-left).\n     */\n    public readonly viewportFrame: Rectangle;\n\n    private renderer: Renderer;\n\n    /** Does the renderer have alpha and are its color channels stored premultipled by the alpha channel? */\n    private _rendererPremultipliedAlpha: boolean;\n\n    /**\n     * @param renderer - The renderer this System works for.\n     */\n    constructor(renderer: Renderer)\n    {\n        this.renderer = renderer;\n\n        this.defaultMaskStack = [];\n        this.current = null;\n        this.sourceFrame = new Rectangle();\n        this.destinationFrame = new Rectangle();\n        this.viewportFrame = new Rectangle();\n    }\n\n    protected contextChange(): void\n    {\n        const attributes = this.renderer?.gl.getContextAttributes();\n\n        this._rendererPremultipliedAlpha = !!(attributes && attributes.alpha && attributes.premultipliedAlpha);\n    }\n\n    /**\n     * Bind the current render texture.\n     * @param renderTexture - RenderTexture to bind, by default its `null` - the screen.\n     * @param sourceFrame - Part of world that is mapped to the renderTexture.\n     * @param destinationFrame - Part of renderTexture, by default it has the same size as sourceFrame.\n     */\n    bind(renderTexture: RenderTexture = null, sourceFrame?: Rectangle, destinationFrame?: Rectangle): void\n    {\n        const renderer = this.renderer;\n\n        this.current = renderTexture;\n\n        let baseTexture: BaseRenderTexture;\n        let framebuffer;\n        let resolution;\n\n        if (renderTexture)\n        {\n            baseTexture = renderTexture.baseTexture as BaseRenderTexture;\n\n            resolution = baseTexture.resolution;\n\n            if (!sourceFrame)\n            {\n                tempRect.width = renderTexture.frame.width;\n                tempRect.height = renderTexture.frame.height;\n\n                sourceFrame = tempRect;\n            }\n\n            if (!destinationFrame)\n            {\n                tempRect2.x = renderTexture.frame.x;\n                tempRect2.y = renderTexture.frame.y;\n                tempRect2.width = sourceFrame.width;\n                tempRect2.height = sourceFrame.height;\n\n                destinationFrame = tempRect2;\n            }\n\n            framebuffer = baseTexture.framebuffer;\n        }\n        else\n        {\n            resolution = renderer.resolution;\n\n            if (!sourceFrame)\n            {\n                tempRect.width = renderer._view.screen.width;\n                tempRect.height = renderer._view.screen.height;\n\n                sourceFrame = tempRect;\n            }\n\n            if (!destinationFrame)\n            {\n                destinationFrame = tempRect;\n\n                destinationFrame.width = sourceFrame.width;\n                destinationFrame.height = sourceFrame.height;\n            }\n        }\n\n        const viewportFrame = this.viewportFrame;\n\n        viewportFrame.x = destinationFrame.x * resolution;\n        viewportFrame.y = destinationFrame.y * resolution;\n        viewportFrame.width = destinationFrame.width * resolution;\n        viewportFrame.height = destinationFrame.height * resolution;\n\n        if (!renderTexture)\n        {\n            viewportFrame.y = renderer.view.height - (viewportFrame.y + viewportFrame.height);\n        }\n\n        viewportFrame.ceil();\n\n        this.renderer.framebuffer.bind(framebuffer, viewportFrame);\n        this.renderer.projection.update(destinationFrame, sourceFrame, resolution, !framebuffer);\n\n        if (renderTexture)\n        {\n            this.renderer.mask.setMaskStack(baseTexture.maskStack);\n        }\n        else\n        {\n            this.renderer.mask.setMaskStack(this.defaultMaskStack);\n        }\n\n        this.sourceFrame.copyFrom(sourceFrame);\n        this.destinationFrame.copyFrom(destinationFrame);\n    }\n\n    /**\n     * Erases the render texture and fills the drawing area with a colour.\n     * @param clearColor - The color as rgba, default to use the renderer backgroundColor\n     * @param [mask=BUFFER_BITS.COLOR | BUFFER_BITS.DEPTH] - Bitwise OR of masks\n     *  that indicate the buffers to be cleared, by default COLOR and DEPTH buffers.\n     */\n    clear(clearColor?: ColorSource, mask?: BUFFER_BITS): void\n    {\n        const fallbackColor = this.current\n            ? this.current.baseTexture.clear\n            : this.renderer.background.backgroundColor;\n        const color = Color.shared.setValue(clearColor ? clearColor : fallbackColor);\n\n        if ((this.current && this.current.baseTexture.alphaMode > 0)\n            || (!this.current && this._rendererPremultipliedAlpha))\n        {\n            color.premultiply(color.alpha);\n        }\n\n        const destinationFrame = this.destinationFrame;\n        const baseFrame: ISize = this.current ? this.current.baseTexture : this.renderer._view.screen;\n        const clearMask = destinationFrame.width !== baseFrame.width || destinationFrame.height !== baseFrame.height;\n\n        if (clearMask)\n        {\n            let { x, y, width, height } = this.viewportFrame;\n\n            x = Math.round(x);\n            y = Math.round(y);\n            width = Math.round(width);\n            height = Math.round(height);\n\n            // TODO: ScissorSystem should cache whether the scissor test is enabled or not.\n            this.renderer.gl.enable(this.renderer.gl.SCISSOR_TEST);\n            this.renderer.gl.scissor(x, y, width, height);\n        }\n\n        this.renderer.framebuffer.clear(color.red, color.green, color.blue, color.alpha, mask);\n\n        if (clearMask)\n        {\n            // Restore the scissor box\n            this.renderer.scissor.pop();\n        }\n    }\n\n    resize(): void // screenWidth, screenHeight)\n    {\n        // resize the root only!\n        this.bind(null);\n    }\n\n    /** Resets render-texture state. */\n    reset(): void\n    {\n        this.bind(null);\n    }\n\n    destroy(): void\n    {\n        this.renderer = null;\n    }\n}\n\nextensions.add(RenderTextureSystem);\n"],"names":[],"mappings":"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"}