diff --git a/packages/core/src/filters/FilterSystem.js b/packages/core/src/filters/FilterSystem.js index 9d1b385..842c1a0 100644 --- a/packages/core/src/filters/FilterSystem.js +++ b/packages/core/src/filters/FilterSystem.js @@ -1,10 +1,9 @@ import System from '../System'; -import RenderTexture from '../renderTexture/RenderTexture'; +import RenderTexturePool from '../renderTexture/RenderTexturePool'; import Quad from '../utils/Quad'; import QuadUv from '../utils/QuadUv'; import { Rectangle, Matrix } from '@pixi/math'; -import { nextPow2 } from '@pixi/utils'; import UniformGroup from '../shader/UniformGroup'; import { DRAW_MODES } from '@pixi/constants'; @@ -81,8 +80,6 @@ } } -const screenKey = 'screen'; - /** * System plugin to the renderer to manage the filters. * @@ -110,7 +107,7 @@ * stores a bunch of PO2 textures used for filtering * @member {Object} */ - this.texturePool = {}; + this.texturePool = new RenderTexturePool(renderer); /** * a pool for storing filter states, save us creating new ones each tick @@ -401,27 +398,16 @@ /** * Destroys this Filter System. - * - * @param {boolean} [contextLost=false] context was lost, do not free shaders - * */ - destroy(contextLost = false) + destroy() { - if (!contextLost) - { - this.emptyPool(); - } - else - { - this.texturePool = {}; - } + // Those textures has to be destroyed by RenderTextureSystem or FramebufferSystem + this.texturePool.clear(false); } /** * Gets a Power-of-Two render texture or fullScreen texture * - * TODO move to a separate class could be on renderer? - * * @protected * @param {number} minWidth - The minimum width of the render texture in real pixels. * @param {number} minHeight - The minimum height of the render texture in real pixels. @@ -430,37 +416,7 @@ */ getOptimalFilterTexture(minWidth, minHeight, resolution = 1) { - let key = screenKey; - - minWidth *= resolution; - minHeight *= resolution; - - if (minWidth !== this._pixelsWidth || minHeight !== this._pixelsHeight) - { - minWidth = nextPow2(minWidth); - minHeight = nextPow2(minHeight); - key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF); - } - - if (!this.texturePool[key]) - { - this.texturePool[key] = []; - } - - let renderTexture = this.texturePool[key].pop(); - - if (!renderTexture) - { - renderTexture = RenderTexture.create({ - width: minWidth, - height: minHeight, - }); - } - - renderTexture.filterPoolKey = key; - renderTexture.setResolution(resolution); - - return renderTexture; + return this.texturePool.getOptimalTexture(minWidth, minHeight, resolution); } /** @@ -472,8 +428,7 @@ getFilterTexture(resolution) { const rt = this.activeState.renderTexture; - - const filterTexture = this.getOptimalFilterTexture(rt.width, rt.height, resolution || rt.baseTexture.resolution); + const filterTexture = this.texturePool.getOptimalTexture(rt.width, rt.height, resolution || rt.resolution); filterTexture.filterFrame = rt.filterFrame; @@ -487,48 +442,22 @@ */ returnFilterTexture(renderTexture) { - const key = renderTexture.filterPoolKey; - - renderTexture.filterFrame = null; - this.texturePool[key].push(renderTexture); + this.texturePool.returnTexture(renderTexture); } /** * Empties the texture pool. - * */ emptyPool() { - for (const i in this.texturePool) - { - const textures = this.texturePool[i]; - - if (textures) - { - for (let j = 0; j < textures.length; j++) - { - textures[j].destroy(true); - } - } - } - - this.texturePool = {}; + this.texturePool.clear(true); } + /** + * calls `texturePool.resize()`, affects fullScreen renderTextures + */ resize() { - const textures = this.texturePool[screenKey]; - - if (textures) - { - for (let j = 0; j < textures.length; j++) - { - textures[j].destroy(true); - } - } - this.texturePool[screenKey] = []; - - this._pixelsWidth = this.renderer.view.width; - this._pixelsHeight = this.renderer.view.height; + this.texturePool.resize(); } } diff --git a/packages/core/src/filters/FilterSystem.js b/packages/core/src/filters/FilterSystem.js index 9d1b385..842c1a0 100644 --- a/packages/core/src/filters/FilterSystem.js +++ b/packages/core/src/filters/FilterSystem.js @@ -1,10 +1,9 @@ import System from '../System'; -import RenderTexture from '../renderTexture/RenderTexture'; +import RenderTexturePool from '../renderTexture/RenderTexturePool'; import Quad from '../utils/Quad'; import QuadUv from '../utils/QuadUv'; import { Rectangle, Matrix } from '@pixi/math'; -import { nextPow2 } from '@pixi/utils'; import UniformGroup from '../shader/UniformGroup'; import { DRAW_MODES } from '@pixi/constants'; @@ -81,8 +80,6 @@ } } -const screenKey = 'screen'; - /** * System plugin to the renderer to manage the filters. * @@ -110,7 +107,7 @@ * stores a bunch of PO2 textures used for filtering * @member {Object} */ - this.texturePool = {}; + this.texturePool = new RenderTexturePool(renderer); /** * a pool for storing filter states, save us creating new ones each tick @@ -401,27 +398,16 @@ /** * Destroys this Filter System. - * - * @param {boolean} [contextLost=false] context was lost, do not free shaders - * */ - destroy(contextLost = false) + destroy() { - if (!contextLost) - { - this.emptyPool(); - } - else - { - this.texturePool = {}; - } + // Those textures has to be destroyed by RenderTextureSystem or FramebufferSystem + this.texturePool.clear(false); } /** * Gets a Power-of-Two render texture or fullScreen texture * - * TODO move to a separate class could be on renderer? - * * @protected * @param {number} minWidth - The minimum width of the render texture in real pixels. * @param {number} minHeight - The minimum height of the render texture in real pixels. @@ -430,37 +416,7 @@ */ getOptimalFilterTexture(minWidth, minHeight, resolution = 1) { - let key = screenKey; - - minWidth *= resolution; - minHeight *= resolution; - - if (minWidth !== this._pixelsWidth || minHeight !== this._pixelsHeight) - { - minWidth = nextPow2(minWidth); - minHeight = nextPow2(minHeight); - key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF); - } - - if (!this.texturePool[key]) - { - this.texturePool[key] = []; - } - - let renderTexture = this.texturePool[key].pop(); - - if (!renderTexture) - { - renderTexture = RenderTexture.create({ - width: minWidth, - height: minHeight, - }); - } - - renderTexture.filterPoolKey = key; - renderTexture.setResolution(resolution); - - return renderTexture; + return this.texturePool.getOptimalTexture(minWidth, minHeight, resolution); } /** @@ -472,8 +428,7 @@ getFilterTexture(resolution) { const rt = this.activeState.renderTexture; - - const filterTexture = this.getOptimalFilterTexture(rt.width, rt.height, resolution || rt.baseTexture.resolution); + const filterTexture = this.texturePool.getOptimalTexture(rt.width, rt.height, resolution || rt.resolution); filterTexture.filterFrame = rt.filterFrame; @@ -487,48 +442,22 @@ */ returnFilterTexture(renderTexture) { - const key = renderTexture.filterPoolKey; - - renderTexture.filterFrame = null; - this.texturePool[key].push(renderTexture); + this.texturePool.returnTexture(renderTexture); } /** * Empties the texture pool. - * */ emptyPool() { - for (const i in this.texturePool) - { - const textures = this.texturePool[i]; - - if (textures) - { - for (let j = 0; j < textures.length; j++) - { - textures[j].destroy(true); - } - } - } - - this.texturePool = {}; + this.texturePool.clear(true); } + /** + * calls `texturePool.resize()`, affects fullScreen renderTextures + */ resize() { - const textures = this.texturePool[screenKey]; - - if (textures) - { - for (let j = 0; j < textures.length; j++) - { - textures[j].destroy(true); - } - } - this.texturePool[screenKey] = []; - - this._pixelsWidth = this.renderer.view.width; - this._pixelsHeight = this.renderer.view.height; + this.texturePool.resize(); } } diff --git a/packages/core/src/index.js b/packages/core/src/index.js index 08ba1c1..55a092b 100644 --- a/packages/core/src/index.js +++ b/packages/core/src/index.js @@ -18,6 +18,7 @@ export { default as Texture } from './textures/Texture'; export { default as TextureMatrix } from './textures/TextureMatrix'; export { default as RenderTexture } from './renderTexture/RenderTexture'; +export { default as RenderTexturePool } from './renderTexture/RenderTexturePool'; export { default as BaseRenderTexture } from './renderTexture/BaseRenderTexture'; export { default as TextureUvs } from './textures/TextureUvs'; export { default as State } from './state/State'; diff --git a/packages/core/src/filters/FilterSystem.js b/packages/core/src/filters/FilterSystem.js index 9d1b385..842c1a0 100644 --- a/packages/core/src/filters/FilterSystem.js +++ b/packages/core/src/filters/FilterSystem.js @@ -1,10 +1,9 @@ import System from '../System'; -import RenderTexture from '../renderTexture/RenderTexture'; +import RenderTexturePool from '../renderTexture/RenderTexturePool'; import Quad from '../utils/Quad'; import QuadUv from '../utils/QuadUv'; import { Rectangle, Matrix } from '@pixi/math'; -import { nextPow2 } from '@pixi/utils'; import UniformGroup from '../shader/UniformGroup'; import { DRAW_MODES } from '@pixi/constants'; @@ -81,8 +80,6 @@ } } -const screenKey = 'screen'; - /** * System plugin to the renderer to manage the filters. * @@ -110,7 +107,7 @@ * stores a bunch of PO2 textures used for filtering * @member {Object} */ - this.texturePool = {}; + this.texturePool = new RenderTexturePool(renderer); /** * a pool for storing filter states, save us creating new ones each tick @@ -401,27 +398,16 @@ /** * Destroys this Filter System. - * - * @param {boolean} [contextLost=false] context was lost, do not free shaders - * */ - destroy(contextLost = false) + destroy() { - if (!contextLost) - { - this.emptyPool(); - } - else - { - this.texturePool = {}; - } + // Those textures has to be destroyed by RenderTextureSystem or FramebufferSystem + this.texturePool.clear(false); } /** * Gets a Power-of-Two render texture or fullScreen texture * - * TODO move to a separate class could be on renderer? - * * @protected * @param {number} minWidth - The minimum width of the render texture in real pixels. * @param {number} minHeight - The minimum height of the render texture in real pixels. @@ -430,37 +416,7 @@ */ getOptimalFilterTexture(minWidth, minHeight, resolution = 1) { - let key = screenKey; - - minWidth *= resolution; - minHeight *= resolution; - - if (minWidth !== this._pixelsWidth || minHeight !== this._pixelsHeight) - { - minWidth = nextPow2(minWidth); - minHeight = nextPow2(minHeight); - key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF); - } - - if (!this.texturePool[key]) - { - this.texturePool[key] = []; - } - - let renderTexture = this.texturePool[key].pop(); - - if (!renderTexture) - { - renderTexture = RenderTexture.create({ - width: minWidth, - height: minHeight, - }); - } - - renderTexture.filterPoolKey = key; - renderTexture.setResolution(resolution); - - return renderTexture; + return this.texturePool.getOptimalTexture(minWidth, minHeight, resolution); } /** @@ -472,8 +428,7 @@ getFilterTexture(resolution) { const rt = this.activeState.renderTexture; - - const filterTexture = this.getOptimalFilterTexture(rt.width, rt.height, resolution || rt.baseTexture.resolution); + const filterTexture = this.texturePool.getOptimalTexture(rt.width, rt.height, resolution || rt.resolution); filterTexture.filterFrame = rt.filterFrame; @@ -487,48 +442,22 @@ */ returnFilterTexture(renderTexture) { - const key = renderTexture.filterPoolKey; - - renderTexture.filterFrame = null; - this.texturePool[key].push(renderTexture); + this.texturePool.returnTexture(renderTexture); } /** * Empties the texture pool. - * */ emptyPool() { - for (const i in this.texturePool) - { - const textures = this.texturePool[i]; - - if (textures) - { - for (let j = 0; j < textures.length; j++) - { - textures[j].destroy(true); - } - } - } - - this.texturePool = {}; + this.texturePool.clear(true); } + /** + * calls `texturePool.resize()`, affects fullScreen renderTextures + */ resize() { - const textures = this.texturePool[screenKey]; - - if (textures) - { - for (let j = 0; j < textures.length; j++) - { - textures[j].destroy(true); - } - } - this.texturePool[screenKey] = []; - - this._pixelsWidth = this.renderer.view.width; - this._pixelsHeight = this.renderer.view.height; + this.texturePool.resize(); } } diff --git a/packages/core/src/index.js b/packages/core/src/index.js index 08ba1c1..55a092b 100644 --- a/packages/core/src/index.js +++ b/packages/core/src/index.js @@ -18,6 +18,7 @@ export { default as Texture } from './textures/Texture'; export { default as TextureMatrix } from './textures/TextureMatrix'; export { default as RenderTexture } from './renderTexture/RenderTexture'; +export { default as RenderTexturePool } from './renderTexture/RenderTexturePool'; export { default as BaseRenderTexture } from './renderTexture/BaseRenderTexture'; export { default as TextureUvs } from './textures/TextureUvs'; export { default as State } from './state/State'; diff --git a/packages/core/src/renderTexture/RenderTexturePool.js b/packages/core/src/renderTexture/RenderTexturePool.js new file mode 100644 index 0000000..6eb0b97 --- /dev/null +++ b/packages/core/src/renderTexture/RenderTexturePool.js @@ -0,0 +1,184 @@ +import RenderTexture from './RenderTexture'; +import BaseRenderTexture from './BaseRenderTexture'; +import { nextPow2 } from '@pixi/utils'; + +/** + * Experimental! + * + * Texture pool, used by FilterSystem and plugins + * Stores collection of temporary pow2 or screen-sized renderTextures + * + * @class + * @memberof PIXI + */ +export default class RenderTexturePool +{ + /** + * @param {PIXI.Renderer} renderer - The renderer this System works for. + * @param {object} [textureOptions] - options that will be passed to BaseRenderTexture constructor + */ + constructor(renderer, textureOptions) + { + this.renderer = renderer; + this.texturePool = {}; + this.textureOptions = textureOptions || {}; + /** + * Allow renderTextures of the same size as screen, not just pow2 + * + * @member {boolean} [enableFullScreen=true] + */ + this.enableFullScreen = true; + } + + /** + * creates of texture with params that were specified in pool constructor + * + * @param {number} realWidth width of texture in pixels + * @param {number} realHeight height of texture in pixels + * @returns {RenderTexture} + */ + createTexture(realWidth, realHeight) + { + const baseRenderTexture = new BaseRenderTexture(Object.assign({ + width: realWidth, + height: realHeight, + }, this.textureOptions)); + + return new RenderTexture(baseRenderTexture); + } + + /** + * Gets a Power-of-Two render texture or fullScreen texture + * + * @protected + * @param {number} minWidth - The minimum width of the render texture in real pixels. + * @param {number} minHeight - The minimum height of the render texture in real pixels. + * @param {number} [resolution=1] - The resolution of the render texture. + * @return {PIXI.RenderTexture} The new render texture. + */ + getOptimalTexture(minWidth, minHeight, resolution = 1) + { + let key = RenderTexturePool.SCREEN_KEY; + + minWidth *= resolution; + minHeight *= resolution; + + if (!this.enableFullScreen || minWidth !== this._pixelsWidth || minHeight !== this._pixelsHeight) + { + minWidth = nextPow2(minWidth); + minHeight = nextPow2(minHeight); + key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF); + } + + if (!this.texturePool[key]) + { + this.texturePool[key] = []; + } + + let renderTexture = this.texturePool[key].pop(); + + if (!renderTexture) + { + renderTexture = this.createTexture(minWidth, minHeight); + } + + renderTexture.filterPoolKey = key; + renderTexture.setResolution(resolution); + + return renderTexture; + } + + /** + * Gets extra texture of the same size as current renderTexture + * + * @param {number} [resolution] resolution, by default its the same as in current renderTexture + * @returns {PIXI.RenderTexture} + */ + getFilterTexture(resolution) + { + const rt = this.renderer.renderTexture.current; + + const filterTexture = this.getOptimalTexture(rt.width, rt.height, resolution || rt.baseTexture.resolution); + + filterTexture.filterFrame = rt.filterFrame; + + return filterTexture; + } + + /** + * Place a render texture back into the pool. + * @param {PIXI.RenderTexture} renderTexture - The renderTexture to free + */ + returnTexture(renderTexture) + { + const key = renderTexture.filterPoolKey; + + renderTexture.filterFrame = null; + this.texturePool[key].push(renderTexture); + } + + /** + * Alias for returnTexture, to be compliant with FilterSystem interface + * @param {PIXI.RenderTexture} renderTexture - The renderTexture to free + */ + returnFilterTexture(renderTexture) + { + this.returnTexture(renderTexture); + } + + /** + * Clears the pool + * + * @member {boolean} [destroyTextures=true] destroy all stored textures + */ + clear(destroyTextures) + { + destroyTextures = destroyTextures !== false; + if (destroyTextures) + { + for (const i in this.texturePool) + { + const textures = this.texturePool[i]; + + if (textures) + { + for (let j = 0; j < textures.length; j++) + { + textures[j].destroy(true); + } + } + } + } + + this.texturePool = {}; + } + + /** + * resizes all textures who has the same size as screen + */ + resize() + { + const screenKey = RenderTexturePool.SCREEN_KEY; + const textures = this.texturePool[screenKey]; + + if (textures) + { + for (let j = 0; j < textures.length; j++) + { + textures[j].destroy(true); + } + } + this.texturePool[screenKey] = []; + + this._pixelsWidth = this.renderer.view.width; + this._pixelsHeight = this.renderer.view.height; + } +} + +/** + * Key that is used to store fullscreen renderTextures in a pool + * + * @static + * @const {string} + */ +RenderTexturePool.SCREEN_KEY = 'screen';