diff --git a/packages/core/src/framebuffer/Framebuffer.js b/packages/core/src/framebuffer/Framebuffer.js index ba285d3..482ad1b 100644 --- a/packages/core/src/framebuffer/Framebuffer.js +++ b/packages/core/src/framebuffer/Framebuffer.js @@ -1,3 +1,4 @@ +import Runner from 'mini-runner'; import Texture from '../textures/BaseTexture'; import { FORMATS, TYPES } from '@pixi/constants'; @@ -29,6 +30,8 @@ this.colorTextures = []; this.glFramebuffers = {}; + + this.disposeRunner = new Runner('disposeFramebuffer', 2); } /** @@ -140,4 +143,12 @@ this.depthTexture.setSize(width, height); } } + + /** + * disposes WebGL resources that are connected to this geometry + */ + dispose() + { + this.disposeRunner.run(this, false); + } } diff --git a/packages/core/src/framebuffer/Framebuffer.js b/packages/core/src/framebuffer/Framebuffer.js index ba285d3..482ad1b 100644 --- a/packages/core/src/framebuffer/Framebuffer.js +++ b/packages/core/src/framebuffer/Framebuffer.js @@ -1,3 +1,4 @@ +import Runner from 'mini-runner'; import Texture from '../textures/BaseTexture'; import { FORMATS, TYPES } from '@pixi/constants'; @@ -29,6 +30,8 @@ this.colorTextures = []; this.glFramebuffers = {}; + + this.disposeRunner = new Runner('disposeFramebuffer', 2); } /** @@ -140,4 +143,12 @@ this.depthTexture.setSize(width, height); } } + + /** + * disposes WebGL resources that are connected to this geometry + */ + dispose() + { + this.disposeRunner.run(this, false); + } } diff --git a/packages/core/src/framebuffer/FramebufferSystem.js b/packages/core/src/framebuffer/FramebufferSystem.js index e2552d2..3b2869f 100644 --- a/packages/core/src/framebuffer/FramebufferSystem.js +++ b/packages/core/src/framebuffer/FramebufferSystem.js @@ -13,6 +13,21 @@ export default class FramebufferSystem extends System { /** + * @param {PIXI.Renderer} renderer - The renderer this System works for. + */ + constructor(renderer) + { + super(renderer); + + /** + * A list of managed framebuffers + * @member {PIXI.Framebuffer[]} + * @readonly + */ + this.managedFramebuffers = []; + } + + /** * Sets up the renderer context and necessary buffers. */ contextChange() @@ -24,6 +39,8 @@ this.viewport = new Rectangle(); this.hasMRT = true; + this.disposeAll(true); + // webgl2 if (!gl.drawBuffers) { @@ -85,7 +102,7 @@ else if (fbo.dirtySize !== framebuffer.dirtySize) { fbo.dirtySize = framebuffer.dirtySize; - this.resizeFramebuffer(framebuffer, fbo); + this.resizeFramebuffer(framebuffer); } } @@ -208,6 +225,9 @@ framebuffer.glFramebuffers[this.CONTEXT_UID] = fbo; + this.managedFramebuffers.push(framebuffer); + framebuffer.disposeRunner.add(this); + return fbo; } @@ -216,7 +236,6 @@ * * @protected * @param {PIXI.Framebuffer} framebuffer - * @param {object} fbo Framebuffer object corresponding to renderer context */ resizeFramebuffer(framebuffer) { @@ -330,4 +349,56 @@ // fbo.enableStencil(); } } + + /** + * Disposes framebuffer + * @param {PIXI.Framebuffer} framebuffer framebuffer that has to be disposed of + * @param {boolean} [contextLost=false] If context was lost, we suppress all delete function calls + */ + disposeFramebuffer(framebuffer, contextLost) + { + const fbo = framebuffer.glFramebuffers[this.CONTEXT_UID]; + const gl = this.gl; + + if (!fbo) + { + return; + } + + delete framebuffer.glFramebuffers[this.CONTEXT_UID]; + + const index = this.managedFramebuffers.indexOf(framebuffer); + + if (index >= 0) + { + this.managedFramebuffers.splice(index, 1); + } + + framebuffer.disposeRunner.remove(this); + + if (!contextLost) + { + gl.deleteFramebuffer(fbo.framebuffer); + if (fbo.stencil) + { + gl.deleteRenderbuffer(fbo.stencil); + } + } + } + + /** + * Disposes all framebuffers, but not textures bound to them + * @param {boolean} [contextLost=false] If context was lost, we suppress all delete function calls + */ + disposeAll(contextLost) + { + const list = this.managedFramebuffers; + + this.managedFramebuffers = []; + + for (let i = 0; i < list.count; i++) + { + this.disposeFramebuffer(list[i], contextLost); + } + } } diff --git a/packages/core/src/framebuffer/Framebuffer.js b/packages/core/src/framebuffer/Framebuffer.js index ba285d3..482ad1b 100644 --- a/packages/core/src/framebuffer/Framebuffer.js +++ b/packages/core/src/framebuffer/Framebuffer.js @@ -1,3 +1,4 @@ +import Runner from 'mini-runner'; import Texture from '../textures/BaseTexture'; import { FORMATS, TYPES } from '@pixi/constants'; @@ -29,6 +30,8 @@ this.colorTextures = []; this.glFramebuffers = {}; + + this.disposeRunner = new Runner('disposeFramebuffer', 2); } /** @@ -140,4 +143,12 @@ this.depthTexture.setSize(width, height); } } + + /** + * disposes WebGL resources that are connected to this geometry + */ + dispose() + { + this.disposeRunner.run(this, false); + } } diff --git a/packages/core/src/framebuffer/FramebufferSystem.js b/packages/core/src/framebuffer/FramebufferSystem.js index e2552d2..3b2869f 100644 --- a/packages/core/src/framebuffer/FramebufferSystem.js +++ b/packages/core/src/framebuffer/FramebufferSystem.js @@ -13,6 +13,21 @@ export default class FramebufferSystem extends System { /** + * @param {PIXI.Renderer} renderer - The renderer this System works for. + */ + constructor(renderer) + { + super(renderer); + + /** + * A list of managed framebuffers + * @member {PIXI.Framebuffer[]} + * @readonly + */ + this.managedFramebuffers = []; + } + + /** * Sets up the renderer context and necessary buffers. */ contextChange() @@ -24,6 +39,8 @@ this.viewport = new Rectangle(); this.hasMRT = true; + this.disposeAll(true); + // webgl2 if (!gl.drawBuffers) { @@ -85,7 +102,7 @@ else if (fbo.dirtySize !== framebuffer.dirtySize) { fbo.dirtySize = framebuffer.dirtySize; - this.resizeFramebuffer(framebuffer, fbo); + this.resizeFramebuffer(framebuffer); } } @@ -208,6 +225,9 @@ framebuffer.glFramebuffers[this.CONTEXT_UID] = fbo; + this.managedFramebuffers.push(framebuffer); + framebuffer.disposeRunner.add(this); + return fbo; } @@ -216,7 +236,6 @@ * * @protected * @param {PIXI.Framebuffer} framebuffer - * @param {object} fbo Framebuffer object corresponding to renderer context */ resizeFramebuffer(framebuffer) { @@ -330,4 +349,56 @@ // fbo.enableStencil(); } } + + /** + * Disposes framebuffer + * @param {PIXI.Framebuffer} framebuffer framebuffer that has to be disposed of + * @param {boolean} [contextLost=false] If context was lost, we suppress all delete function calls + */ + disposeFramebuffer(framebuffer, contextLost) + { + const fbo = framebuffer.glFramebuffers[this.CONTEXT_UID]; + const gl = this.gl; + + if (!fbo) + { + return; + } + + delete framebuffer.glFramebuffers[this.CONTEXT_UID]; + + const index = this.managedFramebuffers.indexOf(framebuffer); + + if (index >= 0) + { + this.managedFramebuffers.splice(index, 1); + } + + framebuffer.disposeRunner.remove(this); + + if (!contextLost) + { + gl.deleteFramebuffer(fbo.framebuffer); + if (fbo.stencil) + { + gl.deleteRenderbuffer(fbo.stencil); + } + } + } + + /** + * Disposes all framebuffers, but not textures bound to them + * @param {boolean} [contextLost=false] If context was lost, we suppress all delete function calls + */ + disposeAll(contextLost) + { + const list = this.managedFramebuffers; + + this.managedFramebuffers = []; + + for (let i = 0; i < list.count; i++) + { + this.disposeFramebuffer(list[i], contextLost); + } + } } diff --git a/packages/core/src/renderTexture/BaseRenderTexture.js b/packages/core/src/renderTexture/BaseRenderTexture.js index 24f3a6f..042cab8 100644 --- a/packages/core/src/renderTexture/BaseRenderTexture.js +++ b/packages/core/src/renderTexture/BaseRenderTexture.js @@ -85,7 +85,7 @@ this.clearColor = [0, 0, 0, 0]; - this.frameBuffer = new Framebuffer(this.width * this.resolution, this.height * this.resolution) + this.framebuffer = new Framebuffer(this.width * this.resolution, this.height * this.resolution) .addColorTexture(0, this) .enableStencil(); @@ -116,7 +116,21 @@ { width = Math.ceil(width); height = Math.ceil(height); - this.frameBuffer.resize(width * this.resolution, height * this.resolution); + this.framebuffer.resize(width * this.resolution, height * this.resolution); + } + + /** + * Frees the texture and framebuffer from WebGL memory without destroying this texture object. + * This means you can still use the texture later which will upload it to GPU + * memory again. + * + * @fires PIXI.BaseTexture#dispose + */ + dispose() + { + this.framebuffer.dispose(); + + super.dispose(); } /** @@ -126,6 +140,9 @@ destroy() { super.destroy(true); + + this.framebuffer = null; + this.renderer = null; } } diff --git a/packages/core/src/framebuffer/Framebuffer.js b/packages/core/src/framebuffer/Framebuffer.js index ba285d3..482ad1b 100644 --- a/packages/core/src/framebuffer/Framebuffer.js +++ b/packages/core/src/framebuffer/Framebuffer.js @@ -1,3 +1,4 @@ +import Runner from 'mini-runner'; import Texture from '../textures/BaseTexture'; import { FORMATS, TYPES } from '@pixi/constants'; @@ -29,6 +30,8 @@ this.colorTextures = []; this.glFramebuffers = {}; + + this.disposeRunner = new Runner('disposeFramebuffer', 2); } /** @@ -140,4 +143,12 @@ this.depthTexture.setSize(width, height); } } + + /** + * disposes WebGL resources that are connected to this geometry + */ + dispose() + { + this.disposeRunner.run(this, false); + } } diff --git a/packages/core/src/framebuffer/FramebufferSystem.js b/packages/core/src/framebuffer/FramebufferSystem.js index e2552d2..3b2869f 100644 --- a/packages/core/src/framebuffer/FramebufferSystem.js +++ b/packages/core/src/framebuffer/FramebufferSystem.js @@ -13,6 +13,21 @@ export default class FramebufferSystem extends System { /** + * @param {PIXI.Renderer} renderer - The renderer this System works for. + */ + constructor(renderer) + { + super(renderer); + + /** + * A list of managed framebuffers + * @member {PIXI.Framebuffer[]} + * @readonly + */ + this.managedFramebuffers = []; + } + + /** * Sets up the renderer context and necessary buffers. */ contextChange() @@ -24,6 +39,8 @@ this.viewport = new Rectangle(); this.hasMRT = true; + this.disposeAll(true); + // webgl2 if (!gl.drawBuffers) { @@ -85,7 +102,7 @@ else if (fbo.dirtySize !== framebuffer.dirtySize) { fbo.dirtySize = framebuffer.dirtySize; - this.resizeFramebuffer(framebuffer, fbo); + this.resizeFramebuffer(framebuffer); } } @@ -208,6 +225,9 @@ framebuffer.glFramebuffers[this.CONTEXT_UID] = fbo; + this.managedFramebuffers.push(framebuffer); + framebuffer.disposeRunner.add(this); + return fbo; } @@ -216,7 +236,6 @@ * * @protected * @param {PIXI.Framebuffer} framebuffer - * @param {object} fbo Framebuffer object corresponding to renderer context */ resizeFramebuffer(framebuffer) { @@ -330,4 +349,56 @@ // fbo.enableStencil(); } } + + /** + * Disposes framebuffer + * @param {PIXI.Framebuffer} framebuffer framebuffer that has to be disposed of + * @param {boolean} [contextLost=false] If context was lost, we suppress all delete function calls + */ + disposeFramebuffer(framebuffer, contextLost) + { + const fbo = framebuffer.glFramebuffers[this.CONTEXT_UID]; + const gl = this.gl; + + if (!fbo) + { + return; + } + + delete framebuffer.glFramebuffers[this.CONTEXT_UID]; + + const index = this.managedFramebuffers.indexOf(framebuffer); + + if (index >= 0) + { + this.managedFramebuffers.splice(index, 1); + } + + framebuffer.disposeRunner.remove(this); + + if (!contextLost) + { + gl.deleteFramebuffer(fbo.framebuffer); + if (fbo.stencil) + { + gl.deleteRenderbuffer(fbo.stencil); + } + } + } + + /** + * Disposes all framebuffers, but not textures bound to them + * @param {boolean} [contextLost=false] If context was lost, we suppress all delete function calls + */ + disposeAll(contextLost) + { + const list = this.managedFramebuffers; + + this.managedFramebuffers = []; + + for (let i = 0; i < list.count; i++) + { + this.disposeFramebuffer(list[i], contextLost); + } + } } diff --git a/packages/core/src/renderTexture/BaseRenderTexture.js b/packages/core/src/renderTexture/BaseRenderTexture.js index 24f3a6f..042cab8 100644 --- a/packages/core/src/renderTexture/BaseRenderTexture.js +++ b/packages/core/src/renderTexture/BaseRenderTexture.js @@ -85,7 +85,7 @@ this.clearColor = [0, 0, 0, 0]; - this.frameBuffer = new Framebuffer(this.width * this.resolution, this.height * this.resolution) + this.framebuffer = new Framebuffer(this.width * this.resolution, this.height * this.resolution) .addColorTexture(0, this) .enableStencil(); @@ -116,7 +116,21 @@ { width = Math.ceil(width); height = Math.ceil(height); - this.frameBuffer.resize(width * this.resolution, height * this.resolution); + this.framebuffer.resize(width * this.resolution, height * this.resolution); + } + + /** + * Frees the texture and framebuffer from WebGL memory without destroying this texture object. + * This means you can still use the texture later which will upload it to GPU + * memory again. + * + * @fires PIXI.BaseTexture#dispose + */ + dispose() + { + this.framebuffer.dispose(); + + super.dispose(); } /** @@ -126,6 +140,9 @@ destroy() { super.destroy(true); + + this.framebuffer = null; + this.renderer = null; } } diff --git a/packages/core/src/renderTexture/RenderTextureSystem.js b/packages/core/src/renderTexture/RenderTextureSystem.js index 9004c76..0a1ae42 100644 --- a/packages/core/src/renderTexture/RenderTextureSystem.js +++ b/packages/core/src/renderTexture/RenderTextureSystem.js @@ -92,7 +92,7 @@ sourceFrame = destinationFrame; } - this.renderer.framebuffer.bind(baseTexture.frameBuffer, destinationFrame); + this.renderer.framebuffer.bind(baseTexture.framebuffer, destinationFrame); this.renderer.projection.update(destinationFrame, sourceFrame, resolution, false); this.renderer.stencil.setMaskStack(baseTexture.stencilMaskStack); diff --git a/packages/core/src/framebuffer/Framebuffer.js b/packages/core/src/framebuffer/Framebuffer.js index ba285d3..482ad1b 100644 --- a/packages/core/src/framebuffer/Framebuffer.js +++ b/packages/core/src/framebuffer/Framebuffer.js @@ -1,3 +1,4 @@ +import Runner from 'mini-runner'; import Texture from '../textures/BaseTexture'; import { FORMATS, TYPES } from '@pixi/constants'; @@ -29,6 +30,8 @@ this.colorTextures = []; this.glFramebuffers = {}; + + this.disposeRunner = new Runner('disposeFramebuffer', 2); } /** @@ -140,4 +143,12 @@ this.depthTexture.setSize(width, height); } } + + /** + * disposes WebGL resources that are connected to this geometry + */ + dispose() + { + this.disposeRunner.run(this, false); + } } diff --git a/packages/core/src/framebuffer/FramebufferSystem.js b/packages/core/src/framebuffer/FramebufferSystem.js index e2552d2..3b2869f 100644 --- a/packages/core/src/framebuffer/FramebufferSystem.js +++ b/packages/core/src/framebuffer/FramebufferSystem.js @@ -13,6 +13,21 @@ export default class FramebufferSystem extends System { /** + * @param {PIXI.Renderer} renderer - The renderer this System works for. + */ + constructor(renderer) + { + super(renderer); + + /** + * A list of managed framebuffers + * @member {PIXI.Framebuffer[]} + * @readonly + */ + this.managedFramebuffers = []; + } + + /** * Sets up the renderer context and necessary buffers. */ contextChange() @@ -24,6 +39,8 @@ this.viewport = new Rectangle(); this.hasMRT = true; + this.disposeAll(true); + // webgl2 if (!gl.drawBuffers) { @@ -85,7 +102,7 @@ else if (fbo.dirtySize !== framebuffer.dirtySize) { fbo.dirtySize = framebuffer.dirtySize; - this.resizeFramebuffer(framebuffer, fbo); + this.resizeFramebuffer(framebuffer); } } @@ -208,6 +225,9 @@ framebuffer.glFramebuffers[this.CONTEXT_UID] = fbo; + this.managedFramebuffers.push(framebuffer); + framebuffer.disposeRunner.add(this); + return fbo; } @@ -216,7 +236,6 @@ * * @protected * @param {PIXI.Framebuffer} framebuffer - * @param {object} fbo Framebuffer object corresponding to renderer context */ resizeFramebuffer(framebuffer) { @@ -330,4 +349,56 @@ // fbo.enableStencil(); } } + + /** + * Disposes framebuffer + * @param {PIXI.Framebuffer} framebuffer framebuffer that has to be disposed of + * @param {boolean} [contextLost=false] If context was lost, we suppress all delete function calls + */ + disposeFramebuffer(framebuffer, contextLost) + { + const fbo = framebuffer.glFramebuffers[this.CONTEXT_UID]; + const gl = this.gl; + + if (!fbo) + { + return; + } + + delete framebuffer.glFramebuffers[this.CONTEXT_UID]; + + const index = this.managedFramebuffers.indexOf(framebuffer); + + if (index >= 0) + { + this.managedFramebuffers.splice(index, 1); + } + + framebuffer.disposeRunner.remove(this); + + if (!contextLost) + { + gl.deleteFramebuffer(fbo.framebuffer); + if (fbo.stencil) + { + gl.deleteRenderbuffer(fbo.stencil); + } + } + } + + /** + * Disposes all framebuffers, but not textures bound to them + * @param {boolean} [contextLost=false] If context was lost, we suppress all delete function calls + */ + disposeAll(contextLost) + { + const list = this.managedFramebuffers; + + this.managedFramebuffers = []; + + for (let i = 0; i < list.count; i++) + { + this.disposeFramebuffer(list[i], contextLost); + } + } } diff --git a/packages/core/src/renderTexture/BaseRenderTexture.js b/packages/core/src/renderTexture/BaseRenderTexture.js index 24f3a6f..042cab8 100644 --- a/packages/core/src/renderTexture/BaseRenderTexture.js +++ b/packages/core/src/renderTexture/BaseRenderTexture.js @@ -85,7 +85,7 @@ this.clearColor = [0, 0, 0, 0]; - this.frameBuffer = new Framebuffer(this.width * this.resolution, this.height * this.resolution) + this.framebuffer = new Framebuffer(this.width * this.resolution, this.height * this.resolution) .addColorTexture(0, this) .enableStencil(); @@ -116,7 +116,21 @@ { width = Math.ceil(width); height = Math.ceil(height); - this.frameBuffer.resize(width * this.resolution, height * this.resolution); + this.framebuffer.resize(width * this.resolution, height * this.resolution); + } + + /** + * Frees the texture and framebuffer from WebGL memory without destroying this texture object. + * This means you can still use the texture later which will upload it to GPU + * memory again. + * + * @fires PIXI.BaseTexture#dispose + */ + dispose() + { + this.framebuffer.dispose(); + + super.dispose(); } /** @@ -126,6 +140,9 @@ destroy() { super.destroy(true); + + this.framebuffer = null; + this.renderer = null; } } diff --git a/packages/core/src/renderTexture/RenderTextureSystem.js b/packages/core/src/renderTexture/RenderTextureSystem.js index 9004c76..0a1ae42 100644 --- a/packages/core/src/renderTexture/RenderTextureSystem.js +++ b/packages/core/src/renderTexture/RenderTextureSystem.js @@ -92,7 +92,7 @@ sourceFrame = destinationFrame; } - this.renderer.framebuffer.bind(baseTexture.frameBuffer, destinationFrame); + this.renderer.framebuffer.bind(baseTexture.framebuffer, destinationFrame); this.renderer.projection.update(destinationFrame, sourceFrame, resolution, false); this.renderer.stencil.setMaskStack(baseTexture.stencilMaskStack); diff --git a/packages/core/src/textures/TextureGCSystem.js b/packages/core/src/textures/TextureGCSystem.js index 2ea8f9a..b725550 100644 --- a/packages/core/src/textures/TextureGCSystem.js +++ b/packages/core/src/textures/TextureGCSystem.js @@ -93,7 +93,7 @@ const texture = managedTextures[i]; // only supports non generated textures at the moment! - if (!texture.frameBuffer && this.count - texture.touched > this.maxIdle) + if (!texture.framebuffer && this.count - texture.touched > this.maxIdle) { tm.destroyTexture(texture, true); managedTextures[i] = null;