UNPKG

32.7 kBSource Map (JSON)View Raw
1{"version":3,"file":"FramebufferSystem.mjs","sources":["../../src/framebuffer/FramebufferSystem.ts"],"sourcesContent":["import { BUFFER_BITS, ENV, MSAA_QUALITY } from '@pixi/constants';\nimport { extensions, ExtensionType } from '@pixi/extensions';\nimport { Rectangle } from '@pixi/math';\nimport { settings } from '@pixi/settings';\nimport { Framebuffer } from './Framebuffer';\nimport { GLFramebuffer } from './GLFramebuffer';\n\nimport type { ExtensionMetadata } from '@pixi/extensions';\nimport type { IRenderingContext } from '../IRenderer';\nimport type { Renderer } from '../Renderer';\nimport type { ISystem } from '../system/ISystem';\n\nconst tempRectangle = new Rectangle();\n\n/**\n * System plugin to the renderer to manage framebuffers.\n * @memberof PIXI\n */\nexport class FramebufferSystem implements ISystem\n{\n /** @ignore */\n static extension: ExtensionMetadata = {\n type: ExtensionType.RendererSystem,\n name: 'framebuffer',\n };\n\n /** A list of managed framebuffers. */\n public readonly managedFramebuffers: Array<Framebuffer>;\n public current: Framebuffer;\n public viewport: Rectangle;\n public hasMRT: boolean;\n public writeDepthTexture: boolean;\n protected CONTEXT_UID: number;\n protected gl: IRenderingContext;\n\n /** Framebuffer value that shows that we don't know what is bound. */\n protected unknownFramebuffer: Framebuffer;\n protected msaaSamples: Array<number>;\n public renderer: Renderer;\n\n /**\n * @param renderer - The renderer this System works for.\n */\n constructor(renderer: Renderer)\n {\n this.renderer = renderer;\n this.managedFramebuffers = [];\n this.unknownFramebuffer = new Framebuffer(10, 10);\n\n this.msaaSamples = null;\n }\n\n /** Sets up the renderer context and necessary buffers. */\n protected contextChange(): void\n {\n this.disposeAll(true);\n\n const gl = this.gl = this.renderer.gl;\n\n this.CONTEXT_UID = this.renderer.CONTEXT_UID;\n this.current = this.unknownFramebuffer;\n this.viewport = new Rectangle();\n this.hasMRT = true;\n this.writeDepthTexture = true;\n\n // webgl2\n if (this.renderer.context.webGLVersion === 1)\n {\n // webgl 1!\n let nativeDrawBuffersExtension = this.renderer.context.extensions.drawBuffers;\n let nativeDepthTextureExtension = this.renderer.context.extensions.depthTexture;\n\n if (settings.PREFER_ENV === ENV.WEBGL_LEGACY)\n {\n nativeDrawBuffersExtension = null;\n nativeDepthTextureExtension = null;\n }\n\n if (nativeDrawBuffersExtension)\n {\n gl.drawBuffers = (activeTextures: number[]): void =>\n nativeDrawBuffersExtension.drawBuffersWEBGL(activeTextures);\n }\n else\n {\n this.hasMRT = false;\n gl.drawBuffers = (): void =>\n {\n // empty\n };\n }\n\n if (!nativeDepthTextureExtension)\n {\n this.writeDepthTexture = false;\n }\n }\n else\n {\n // WebGL2\n // cache possible MSAA samples\n this.msaaSamples = gl.getInternalformatParameter(gl.RENDERBUFFER, gl.RGBA8, gl.SAMPLES);\n }\n }\n\n /**\n * Bind a framebuffer.\n * @param framebuffer\n * @param frame - frame, default is framebuffer size\n * @param mipLevel - optional mip level to set on the framebuffer - defaults to 0\n */\n bind(framebuffer?: Framebuffer, frame?: Rectangle, mipLevel = 0): void\n {\n const { gl } = this;\n\n if (framebuffer)\n {\n // TODO caching layer!\n\n const fbo = framebuffer.glFramebuffers[this.CONTEXT_UID] || this.initFramebuffer(framebuffer);\n\n if (this.current !== framebuffer)\n {\n this.current = framebuffer;\n gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer);\n }\n // make sure all textures are unbound..\n\n if (fbo.mipLevel !== mipLevel)\n {\n framebuffer.dirtyId++;\n framebuffer.dirtyFormat++;\n fbo.mipLevel = mipLevel;\n }\n\n // now check for updates...\n if (fbo.dirtyId !== framebuffer.dirtyId)\n {\n fbo.dirtyId = framebuffer.dirtyId;\n\n if (fbo.dirtyFormat !== framebuffer.dirtyFormat)\n {\n fbo.dirtyFormat = framebuffer.dirtyFormat;\n fbo.dirtySize = framebuffer.dirtySize;\n this.updateFramebuffer(framebuffer, mipLevel);\n }\n else if (fbo.dirtySize !== framebuffer.dirtySize)\n {\n fbo.dirtySize = framebuffer.dirtySize;\n this.resizeFramebuffer(framebuffer);\n }\n }\n\n for (let i = 0; i < framebuffer.colorTextures.length; i++)\n {\n const tex = framebuffer.colorTextures[i];\n\n this.renderer.texture.unbind(tex.parentTextureArray || tex);\n }\n\n if (framebuffer.depthTexture)\n {\n this.renderer.texture.unbind(framebuffer.depthTexture);\n }\n\n if (frame)\n {\n const mipWidth = (frame.width >> mipLevel);\n const mipHeight = (frame.height >> mipLevel);\n\n const scale = mipWidth / frame.width;\n\n this.setViewport(\n frame.x * scale,\n frame.y * scale,\n mipWidth,\n mipHeight\n );\n }\n else\n {\n const mipWidth = (framebuffer.width >> mipLevel);\n const mipHeight = (framebuffer.height >> mipLevel);\n\n this.setViewport(0, 0, mipWidth, mipHeight);\n }\n }\n else\n {\n if (this.current)\n {\n this.current = null;\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n }\n\n if (frame)\n {\n this.setViewport(frame.x, frame.y, frame.width, frame.height);\n }\n else\n {\n this.setViewport(0, 0, this.renderer.width, this.renderer.height);\n }\n }\n }\n\n /**\n * Set the WebGLRenderingContext's viewport.\n * @param x - X position of viewport\n * @param y - Y position of viewport\n * @param width - Width of viewport\n * @param height - Height of viewport\n */\n setViewport(x: number, y: number, width: number, height: number): void\n {\n const v = this.viewport;\n\n x = Math.round(x);\n y = Math.round(y);\n width = Math.round(width);\n height = Math.round(height);\n\n if (v.width !== width || v.height !== height || v.x !== x || v.y !== y)\n {\n v.x = x;\n v.y = y;\n v.width = width;\n v.height = height;\n\n this.gl.viewport(x, y, width, height);\n }\n }\n\n /**\n * Get the size of the current width and height. Returns object with `width` and `height` values.\n * @readonly\n */\n get size(): { x: number; y: number; width: number; height: number }\n {\n if (this.current)\n {\n // TODO store temp\n return { x: 0, y: 0, width: this.current.width, height: this.current.height };\n }\n\n return { x: 0, y: 0, width: this.renderer.width, height: this.renderer.height };\n }\n\n /**\n * Clear the color of the context\n * @param r - Red value from 0 to 1\n * @param g - Green value from 0 to 1\n * @param b - Blue value from 0 to 1\n * @param a - Alpha value from 0 to 1\n * @param {PIXI.BUFFER_BITS} [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(r: number, g: number, b: number, a: number, mask: BUFFER_BITS = BUFFER_BITS.COLOR | BUFFER_BITS.DEPTH): void\n {\n const { gl } = this;\n\n // TODO clear color can be set only one right?\n gl.clearColor(r, g, b, a);\n gl.clear(mask);\n }\n\n /**\n * Initialize framebuffer for this context\n * @protected\n * @param framebuffer\n * @returns - created GLFramebuffer\n */\n initFramebuffer(framebuffer: Framebuffer): GLFramebuffer\n {\n const { gl } = this;\n const fbo = new GLFramebuffer(gl.createFramebuffer());\n\n fbo.multisample = this.detectSamples(framebuffer.multisample);\n framebuffer.glFramebuffers[this.CONTEXT_UID] = fbo;\n\n this.managedFramebuffers.push(framebuffer);\n framebuffer.disposeRunner.add(this);\n\n return fbo;\n }\n\n /**\n * Resize the framebuffer\n * @param framebuffer\n * @protected\n */\n resizeFramebuffer(framebuffer: Framebuffer): void\n {\n const { gl } = this;\n\n const fbo = framebuffer.glFramebuffers[this.CONTEXT_UID];\n\n if (fbo.stencil)\n {\n gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.stencil);\n\n let stencilFormat: number;\n\n if (this.renderer.context.webGLVersion === 1)\n {\n stencilFormat = gl.DEPTH_STENCIL;\n }\n else if (framebuffer.depth && framebuffer.stencil)\n {\n stencilFormat = gl.DEPTH24_STENCIL8;\n }\n else if (framebuffer.depth)\n {\n stencilFormat = gl.DEPTH_COMPONENT24;\n }\n else\n {\n stencilFormat = gl.STENCIL_INDEX8;\n }\n\n if (fbo.msaaBuffer)\n {\n gl.renderbufferStorageMultisample(gl.RENDERBUFFER, fbo.multisample,\n stencilFormat, framebuffer.width, framebuffer.height);\n }\n else\n {\n gl.renderbufferStorage(gl.RENDERBUFFER, stencilFormat, framebuffer.width, framebuffer.height);\n }\n }\n\n const colorTextures = framebuffer.colorTextures;\n\n let count = colorTextures.length;\n\n if (!gl.drawBuffers)\n {\n count = Math.min(count, 1);\n }\n\n for (let i = 0; i < count; i++)\n {\n const texture = colorTextures[i];\n const parentTexture = texture.parentTextureArray || texture;\n\n this.renderer.texture.bind(parentTexture, 0);\n\n if (i === 0 && fbo.msaaBuffer)\n {\n gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.msaaBuffer);\n gl.renderbufferStorageMultisample(gl.RENDERBUFFER, fbo.multisample,\n parentTexture._glTextures[this.CONTEXT_UID].internalFormat, framebuffer.width, framebuffer.height);\n }\n }\n\n if (framebuffer.depthTexture && this.writeDepthTexture)\n {\n this.renderer.texture.bind(framebuffer.depthTexture, 0);\n }\n }\n\n /**\n * Update the framebuffer\n * @param framebuffer\n * @param mipLevel\n * @protected\n */\n updateFramebuffer(framebuffer: Framebuffer, mipLevel: number): void\n {\n const { gl } = this;\n\n const fbo = framebuffer.glFramebuffers[this.CONTEXT_UID];\n\n // bind the color texture\n const colorTextures = framebuffer.colorTextures;\n\n let count = colorTextures.length;\n\n if (!gl.drawBuffers)\n {\n count = Math.min(count, 1);\n }\n\n if (fbo.multisample > 1 && this.canMultisampleFramebuffer(framebuffer))\n {\n fbo.msaaBuffer = fbo.msaaBuffer || gl.createRenderbuffer();\n }\n else if (fbo.msaaBuffer)\n {\n gl.deleteRenderbuffer(fbo.msaaBuffer);\n fbo.msaaBuffer = null;\n\n if (fbo.blitFramebuffer)\n {\n fbo.blitFramebuffer.dispose();\n fbo.blitFramebuffer = null;\n }\n }\n\n const activeTextures = [];\n\n for (let i = 0; i < count; i++)\n {\n const texture = colorTextures[i];\n const parentTexture = texture.parentTextureArray || texture;\n\n this.renderer.texture.bind(parentTexture, 0);\n\n if (i === 0 && fbo.msaaBuffer)\n {\n gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.msaaBuffer);\n gl.renderbufferStorageMultisample(gl.RENDERBUFFER, fbo.multisample,\n parentTexture._glTextures[this.CONTEXT_UID].internalFormat, framebuffer.width, framebuffer.height);\n gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, fbo.msaaBuffer);\n }\n else\n {\n gl.framebufferTexture2D(gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0 + i,\n texture.target,\n parentTexture._glTextures[this.CONTEXT_UID].texture,\n mipLevel);\n\n activeTextures.push(gl.COLOR_ATTACHMENT0 + i);\n }\n }\n\n if (activeTextures.length > 1)\n {\n gl.drawBuffers(activeTextures);\n }\n\n if (framebuffer.depthTexture)\n {\n const writeDepthTexture = this.writeDepthTexture;\n\n if (writeDepthTexture)\n {\n const depthTexture = framebuffer.depthTexture;\n\n this.renderer.texture.bind(depthTexture, 0);\n\n gl.framebufferTexture2D(gl.FRAMEBUFFER,\n gl.DEPTH_ATTACHMENT,\n gl.TEXTURE_2D,\n depthTexture._glTextures[this.CONTEXT_UID].texture,\n mipLevel);\n }\n }\n\n if ((framebuffer.stencil || framebuffer.depth) && !(framebuffer.depthTexture && this.writeDepthTexture))\n {\n fbo.stencil = fbo.stencil || gl.createRenderbuffer();\n\n let stencilAttachment: number;\n let stencilFormat: number;\n\n if (this.renderer.context.webGLVersion === 1)\n {\n stencilAttachment = gl.DEPTH_STENCIL_ATTACHMENT;\n stencilFormat = gl.DEPTH_STENCIL;\n }\n else if (framebuffer.depth && framebuffer.stencil)\n {\n stencilAttachment = gl.DEPTH_STENCIL_ATTACHMENT;\n stencilFormat = gl.DEPTH24_STENCIL8;\n }\n else if (framebuffer.depth)\n {\n stencilAttachment = gl.DEPTH_ATTACHMENT;\n stencilFormat = gl.DEPTH_COMPONENT24;\n }\n else\n {\n stencilAttachment = gl.STENCIL_ATTACHMENT;\n stencilFormat = gl.STENCIL_INDEX8;\n }\n\n gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.stencil);\n\n if (fbo.msaaBuffer)\n {\n gl.renderbufferStorageMultisample(gl.RENDERBUFFER, fbo.multisample, stencilFormat,\n framebuffer.width, framebuffer.height);\n }\n else\n {\n gl.renderbufferStorage(gl.RENDERBUFFER, stencilFormat, framebuffer.width, framebuffer.height);\n }\n\n gl.framebufferRenderbuffer(gl.FRAMEBUFFER, stencilAttachment, gl.RENDERBUFFER, fbo.stencil);\n }\n else if (fbo.stencil)\n {\n gl.deleteRenderbuffer(fbo.stencil);\n fbo.stencil = null;\n }\n }\n\n /**\n * Returns true if the frame buffer can be multisampled.\n * @param framebuffer\n */\n protected canMultisampleFramebuffer(framebuffer: Framebuffer): boolean\n {\n return this.renderer.context.webGLVersion !== 1\n && framebuffer.colorTextures.length <= 1 && !framebuffer.depthTexture;\n }\n\n /**\n * Detects number of samples that is not more than a param but as close to it as possible\n * @param samples - number of samples\n * @returns - recommended number of samples\n */\n protected detectSamples(samples: MSAA_QUALITY): MSAA_QUALITY\n {\n const { msaaSamples } = this;\n let res: number = MSAA_QUALITY.NONE;\n\n if (samples <= 1 || msaaSamples === null)\n {\n return res;\n }\n for (let i = 0; i < msaaSamples.length; i++)\n {\n if (msaaSamples[i] <= samples)\n {\n res = msaaSamples[i];\n break;\n }\n }\n\n if (res === 1)\n {\n res = MSAA_QUALITY.NONE;\n }\n\n return res;\n }\n\n /**\n * Only works with WebGL2\n *\n * blits framebuffer to another of the same or bigger size\n * after that target framebuffer is bound\n *\n * Fails with WebGL warning if blits multisample framebuffer to different size\n * @param framebuffer - by default it blits \"into itself\", from renderBuffer to texture.\n * @param sourcePixels - source rectangle in pixels\n * @param destPixels - dest rectangle in pixels, assumed to be the same as sourcePixels\n */\n public blit(framebuffer?: Framebuffer, sourcePixels?: Rectangle, destPixels?: Rectangle): void\n {\n const { current, renderer, gl, CONTEXT_UID } = this;\n\n if (renderer.context.webGLVersion !== 2)\n {\n return;\n }\n\n if (!current)\n {\n return;\n }\n const fbo = current.glFramebuffers[CONTEXT_UID];\n\n if (!fbo)\n {\n return;\n }\n if (!framebuffer)\n {\n if (!fbo.msaaBuffer)\n {\n return;\n }\n\n const colorTexture = current.colorTextures[0];\n\n if (!colorTexture)\n {\n return;\n }\n\n if (!fbo.blitFramebuffer)\n {\n fbo.blitFramebuffer = new Framebuffer(current.width, current.height);\n fbo.blitFramebuffer.addColorTexture(0, colorTexture);\n }\n\n framebuffer = fbo.blitFramebuffer;\n\n if (framebuffer.colorTextures[0] !== colorTexture)\n {\n framebuffer.colorTextures[0] = colorTexture;\n framebuffer.dirtyId++;\n framebuffer.dirtyFormat++;\n }\n\n if (framebuffer.width !== current.width || framebuffer.height !== current.height)\n {\n framebuffer.width = current.width;\n framebuffer.height = current.height;\n framebuffer.dirtyId++;\n framebuffer.dirtySize++;\n }\n }\n\n if (!sourcePixels)\n {\n sourcePixels = tempRectangle;\n sourcePixels.width = current.width;\n sourcePixels.height = current.height;\n }\n if (!destPixels)\n {\n destPixels = sourcePixels;\n }\n\n const sameSize = sourcePixels.width === destPixels.width && sourcePixels.height === destPixels.height;\n\n this.bind(framebuffer);\n gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo.framebuffer);\n gl.blitFramebuffer(\n sourcePixels.left, sourcePixels.top, sourcePixels.right, sourcePixels.bottom,\n destPixels.left, destPixels.top, destPixels.right, destPixels.bottom,\n gl.COLOR_BUFFER_BIT, sameSize ? gl.NEAREST : gl.LINEAR\n );\n gl.bindFramebuffer(gl.READ_FRAMEBUFFER, framebuffer.glFramebuffers[this.CONTEXT_UID].framebuffer);\n }\n\n /**\n * Disposes framebuffer.\n * @param framebuffer - framebuffer that has to be disposed of\n * @param contextLost - If context was lost, we suppress all delete function calls\n */\n disposeFramebuffer(framebuffer: Framebuffer, contextLost?: boolean): void\n {\n const fbo = framebuffer.glFramebuffers[this.CONTEXT_UID];\n const gl = this.gl;\n\n if (!fbo)\n {\n return;\n }\n\n delete framebuffer.glFramebuffers[this.CONTEXT_UID];\n\n const index = this.managedFramebuffers.indexOf(framebuffer);\n\n if (index >= 0)\n {\n this.managedFramebuffers.splice(index, 1);\n }\n\n framebuffer.disposeRunner.remove(this);\n\n if (!contextLost)\n {\n gl.deleteFramebuffer(fbo.framebuffer);\n\n if (fbo.msaaBuffer)\n {\n gl.deleteRenderbuffer(fbo.msaaBuffer);\n }\n\n if (fbo.stencil)\n {\n gl.deleteRenderbuffer(fbo.stencil);\n }\n }\n\n if (fbo.blitFramebuffer)\n {\n this.disposeFramebuffer(fbo.blitFramebuffer, contextLost);\n }\n }\n\n /**\n * Disposes all framebuffers, but not textures bound to them.\n * @param [contextLost=false] - If context was lost, we suppress all delete function calls\n */\n disposeAll(contextLost?: boolean): void\n {\n const list = this.managedFramebuffers;\n\n (this.managedFramebuffers as any) = [];\n\n for (let i = 0; i < list.length; i++)\n {\n this.disposeFramebuffer(list[i], contextLost);\n }\n }\n\n /**\n * Forcing creation of stencil buffer for current framebuffer, if it wasn't done before.\n * Used by MaskSystem, when its time to use stencil mask for Graphics element.\n *\n * Its an alternative for public lazy `framebuffer.enableStencil`, in case we need stencil without rebind.\n * @private\n */\n forceStencil(): void\n {\n const framebuffer = this.current;\n\n if (!framebuffer)\n {\n return;\n }\n\n const fbo = framebuffer.glFramebuffers[this.CONTEXT_UID];\n\n if (!fbo || (fbo.stencil && framebuffer.stencil))\n {\n return;\n }\n\n framebuffer.stencil = true;\n\n const w = framebuffer.width;\n const h = framebuffer.height;\n const gl = this.gl;\n const stencil = fbo.stencil = gl.createRenderbuffer();\n\n gl.bindRenderbuffer(gl.RENDERBUFFER, stencil);\n\n let stencilAttachment: number;\n let stencilFormat: number;\n\n if (this.renderer.context.webGLVersion === 1)\n {\n stencilAttachment = gl.DEPTH_STENCIL_ATTACHMENT;\n stencilFormat = gl.DEPTH_STENCIL;\n }\n else if (framebuffer.depth)\n {\n stencilAttachment = gl.DEPTH_STENCIL_ATTACHMENT;\n stencilFormat = gl.DEPTH24_STENCIL8;\n }\n else\n {\n stencilAttachment = gl.STENCIL_ATTACHMENT;\n stencilFormat = gl.STENCIL_INDEX8;\n }\n\n if (fbo.msaaBuffer)\n {\n gl.renderbufferStorageMultisample(gl.RENDERBUFFER, fbo.multisample, stencilFormat, w, h);\n }\n else\n {\n gl.renderbufferStorage(gl.RENDERBUFFER, stencilFormat, w, h);\n }\n\n gl.framebufferRenderbuffer(gl.FRAMEBUFFER, stencilAttachment, gl.RENDERBUFFER, stencil);\n }\n\n /** Resets framebuffer stored state, binds screen framebuffer. Should be called before renderTexture reset(). */\n reset(): void\n {\n this.current = this.unknownFramebuffer;\n this.viewport = new Rectangle();\n }\n\n destroy(): void\n {\n this.renderer = null;\n }\n}\n\nextensions.add(FramebufferSystem);\n"],"names":[],"mappings":"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"}
\No newline at end of file