diff --git a/src/core/renderers/webgl/systems/NewTextureSystem.js b/src/core/renderers/webgl/systems/NewTextureSystem.js index 49e1820..d654e09 100644 --- a/src/core/renderers/webgl/systems/NewTextureSystem.js +++ b/src/core/renderers/webgl/systems/NewTextureSystem.js @@ -1,5 +1,6 @@ import WebGLSystem from './WebGLSystem'; import { GLFramebuffer, GLTexture } from 'pixi-gl-core'; +import { removeItems } from '../../../utils'; /** * @class @@ -14,6 +15,8 @@ constructor(renderer) { super(renderer); + + // TODO set to max textures... this.boundTextures = [ null, null, @@ -35,6 +38,9 @@ ]; this.currentLocation = -1; + + this.managedTextures = []; + } /** @@ -140,6 +146,9 @@ texture._glTextures[this.CONTEXT_UID] = glTexture; + this.managedTextures.push(texture); + texture.on('dispose', this.destroyTexture, this); + return glTexture; } @@ -147,7 +156,6 @@ { const glTexture = texture._glTextures[this.CONTEXT_UID]; const gl = this.gl; - //console.log(gl); // TODO there are only 3 textures as far as im aware? // Cube / 2D and later 3d. (the latter is WebGL2, we will get to that soon!) @@ -223,6 +231,39 @@ this.setStyle(texture); } + /** + * Deletes the texture from WebGL + * + * @param {PIXI.BaseTexture|PIXI.Texture} texture - the texture to destroy + * @param {boolean} [skipRemove=false] - Whether to skip removing the texture from the TextureManager. + */ + destroyTexture(texture, skipRemove) + { + texture = texture.baseTexture || texture; + + console.log(" >>>>> DISPOSE >>>>> "); + + if (texture._glTextures[this.renderer.CONTEXT_UID]) + { + this.unbind(texture); + + texture._glTextures[this.renderer.CONTEXT_UID].destroy(); + texture.off('dispose', this.destroyTexture, this); + + delete texture._glTextures[this.renderer.CONTEXT_UID]; + + if (!skipRemove) + { + const i = this.managedTextures.indexOf(texture); + + if (i !== -1) + { + removeItems(this.managedTextures, i, 1); + } + } + } + } + setStyle(texture) { const gl = this.gl; diff --git a/src/core/renderers/webgl/systems/NewTextureSystem.js b/src/core/renderers/webgl/systems/NewTextureSystem.js index 49e1820..d654e09 100644 --- a/src/core/renderers/webgl/systems/NewTextureSystem.js +++ b/src/core/renderers/webgl/systems/NewTextureSystem.js @@ -1,5 +1,6 @@ import WebGLSystem from './WebGLSystem'; import { GLFramebuffer, GLTexture } from 'pixi-gl-core'; +import { removeItems } from '../../../utils'; /** * @class @@ -14,6 +15,8 @@ constructor(renderer) { super(renderer); + + // TODO set to max textures... this.boundTextures = [ null, null, @@ -35,6 +38,9 @@ ]; this.currentLocation = -1; + + this.managedTextures = []; + } /** @@ -140,6 +146,9 @@ texture._glTextures[this.CONTEXT_UID] = glTexture; + this.managedTextures.push(texture); + texture.on('dispose', this.destroyTexture, this); + return glTexture; } @@ -147,7 +156,6 @@ { const glTexture = texture._glTextures[this.CONTEXT_UID]; const gl = this.gl; - //console.log(gl); // TODO there are only 3 textures as far as im aware? // Cube / 2D and later 3d. (the latter is WebGL2, we will get to that soon!) @@ -223,6 +231,39 @@ this.setStyle(texture); } + /** + * Deletes the texture from WebGL + * + * @param {PIXI.BaseTexture|PIXI.Texture} texture - the texture to destroy + * @param {boolean} [skipRemove=false] - Whether to skip removing the texture from the TextureManager. + */ + destroyTexture(texture, skipRemove) + { + texture = texture.baseTexture || texture; + + console.log(" >>>>> DISPOSE >>>>> "); + + if (texture._glTextures[this.renderer.CONTEXT_UID]) + { + this.unbind(texture); + + texture._glTextures[this.renderer.CONTEXT_UID].destroy(); + texture.off('dispose', this.destroyTexture, this); + + delete texture._glTextures[this.renderer.CONTEXT_UID]; + + if (!skipRemove) + { + const i = this.managedTextures.indexOf(texture); + + if (i !== -1) + { + removeItems(this.managedTextures, i, 1); + } + } + } + } + setStyle(texture) { const gl = this.gl; diff --git a/src/core/renderers/webgl/systems/TextureGCSystem.js b/src/core/renderers/webgl/systems/TextureGCSystem.js index cd9f24b..4cc7dc2 100644 --- a/src/core/renderers/webgl/systems/TextureGCSystem.js +++ b/src/core/renderers/webgl/systems/TextureGCSystem.js @@ -56,7 +56,7 @@ run() { const tm = this.renderer.texture; - const managedTextures = tm._managedTextures; + const managedTextures = tm.managedTextures; let wasRemoved = false; for (let i = 0; i < managedTextures.length; i++) @@ -64,7 +64,7 @@ const texture = managedTextures[i]; // only supports non generated textures at the moment! - if (!texture._glRenderTargets && this.count - texture.touched > this.maxIdle) + if (!texture.frameBuffer && this.count - texture.touched > this.maxIdle) { tm.destroyTexture(texture, true); managedTextures[i] = null; diff --git a/src/core/renderers/webgl/systems/NewTextureSystem.js b/src/core/renderers/webgl/systems/NewTextureSystem.js index 49e1820..d654e09 100644 --- a/src/core/renderers/webgl/systems/NewTextureSystem.js +++ b/src/core/renderers/webgl/systems/NewTextureSystem.js @@ -1,5 +1,6 @@ import WebGLSystem from './WebGLSystem'; import { GLFramebuffer, GLTexture } from 'pixi-gl-core'; +import { removeItems } from '../../../utils'; /** * @class @@ -14,6 +15,8 @@ constructor(renderer) { super(renderer); + + // TODO set to max textures... this.boundTextures = [ null, null, @@ -35,6 +38,9 @@ ]; this.currentLocation = -1; + + this.managedTextures = []; + } /** @@ -140,6 +146,9 @@ texture._glTextures[this.CONTEXT_UID] = glTexture; + this.managedTextures.push(texture); + texture.on('dispose', this.destroyTexture, this); + return glTexture; } @@ -147,7 +156,6 @@ { const glTexture = texture._glTextures[this.CONTEXT_UID]; const gl = this.gl; - //console.log(gl); // TODO there are only 3 textures as far as im aware? // Cube / 2D and later 3d. (the latter is WebGL2, we will get to that soon!) @@ -223,6 +231,39 @@ this.setStyle(texture); } + /** + * Deletes the texture from WebGL + * + * @param {PIXI.BaseTexture|PIXI.Texture} texture - the texture to destroy + * @param {boolean} [skipRemove=false] - Whether to skip removing the texture from the TextureManager. + */ + destroyTexture(texture, skipRemove) + { + texture = texture.baseTexture || texture; + + console.log(" >>>>> DISPOSE >>>>> "); + + if (texture._glTextures[this.renderer.CONTEXT_UID]) + { + this.unbind(texture); + + texture._glTextures[this.renderer.CONTEXT_UID].destroy(); + texture.off('dispose', this.destroyTexture, this); + + delete texture._glTextures[this.renderer.CONTEXT_UID]; + + if (!skipRemove) + { + const i = this.managedTextures.indexOf(texture); + + if (i !== -1) + { + removeItems(this.managedTextures, i, 1); + } + } + } + } + setStyle(texture) { const gl = this.gl; diff --git a/src/core/renderers/webgl/systems/TextureGCSystem.js b/src/core/renderers/webgl/systems/TextureGCSystem.js index cd9f24b..4cc7dc2 100644 --- a/src/core/renderers/webgl/systems/TextureGCSystem.js +++ b/src/core/renderers/webgl/systems/TextureGCSystem.js @@ -56,7 +56,7 @@ run() { const tm = this.renderer.texture; - const managedTextures = tm._managedTextures; + const managedTextures = tm.managedTextures; let wasRemoved = false; for (let i = 0; i < managedTextures.length; i++) @@ -64,7 +64,7 @@ const texture = managedTextures[i]; // only supports non generated textures at the moment! - if (!texture._glRenderTargets && this.count - texture.touched > this.maxIdle) + if (!texture.frameBuffer && this.count - texture.touched > this.maxIdle) { tm.destroyTexture(texture, true); managedTextures[i] = null; diff --git a/src/core/textures/BaseTexture.js b/src/core/textures/BaseTexture.js index b8a4fcc..64945b6 100644 --- a/src/core/textures/BaseTexture.js +++ b/src/core/textures/BaseTexture.js @@ -111,6 +111,8 @@ this.setResource(resource); } + this.cacheId = null; + this.validate(); } @@ -120,7 +122,8 @@ this.resource = resource; - this.resource.load.then((resource) => { + this.resource.load + .then((resource) => { if(this.resource === resource) { @@ -143,6 +146,12 @@ } }) + .catch((reason)=>{ + + // failed to load - maybe resource was destroyed before it loaded. + console.warn(reason); + + }) this.resource.resourceUpdated.add(this); //calls resourceUpaded } @@ -189,6 +198,45 @@ } /** + * Destroys this base texture + * + */ + destroy() + { + // remove from the cache.. + + if (this.cacheId) + { + delete BaseTextureCache[this.cacheId]; + delete TextureCache[this.cacheId]; + + this.cacheId = null; + } + + // remove and destroy the resource + + if(this.resource) + { + this.resource.destroy(); + this.resource = null; + } + + // finally let the webGL renderer know.. + this.dispose() + } + + /** + * Frees the texture 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. + * + */ + dispose() + { + this.emit('dispose', this); + } + + /** * Helper function that creates a base texture based on the source you provide. * The source can be - image url, image element, canvas element. * @@ -221,6 +269,7 @@ if (!baseTexture) { baseTexture = new BaseTexture(source); + baseTexture.cacheId BaseTextureCache[cacheId] = baseTexture; } diff --git a/src/core/renderers/webgl/systems/NewTextureSystem.js b/src/core/renderers/webgl/systems/NewTextureSystem.js index 49e1820..d654e09 100644 --- a/src/core/renderers/webgl/systems/NewTextureSystem.js +++ b/src/core/renderers/webgl/systems/NewTextureSystem.js @@ -1,5 +1,6 @@ import WebGLSystem from './WebGLSystem'; import { GLFramebuffer, GLTexture } from 'pixi-gl-core'; +import { removeItems } from '../../../utils'; /** * @class @@ -14,6 +15,8 @@ constructor(renderer) { super(renderer); + + // TODO set to max textures... this.boundTextures = [ null, null, @@ -35,6 +38,9 @@ ]; this.currentLocation = -1; + + this.managedTextures = []; + } /** @@ -140,6 +146,9 @@ texture._glTextures[this.CONTEXT_UID] = glTexture; + this.managedTextures.push(texture); + texture.on('dispose', this.destroyTexture, this); + return glTexture; } @@ -147,7 +156,6 @@ { const glTexture = texture._glTextures[this.CONTEXT_UID]; const gl = this.gl; - //console.log(gl); // TODO there are only 3 textures as far as im aware? // Cube / 2D and later 3d. (the latter is WebGL2, we will get to that soon!) @@ -223,6 +231,39 @@ this.setStyle(texture); } + /** + * Deletes the texture from WebGL + * + * @param {PIXI.BaseTexture|PIXI.Texture} texture - the texture to destroy + * @param {boolean} [skipRemove=false] - Whether to skip removing the texture from the TextureManager. + */ + destroyTexture(texture, skipRemove) + { + texture = texture.baseTexture || texture; + + console.log(" >>>>> DISPOSE >>>>> "); + + if (texture._glTextures[this.renderer.CONTEXT_UID]) + { + this.unbind(texture); + + texture._glTextures[this.renderer.CONTEXT_UID].destroy(); + texture.off('dispose', this.destroyTexture, this); + + delete texture._glTextures[this.renderer.CONTEXT_UID]; + + if (!skipRemove) + { + const i = this.managedTextures.indexOf(texture); + + if (i !== -1) + { + removeItems(this.managedTextures, i, 1); + } + } + } + } + setStyle(texture) { const gl = this.gl; diff --git a/src/core/renderers/webgl/systems/TextureGCSystem.js b/src/core/renderers/webgl/systems/TextureGCSystem.js index cd9f24b..4cc7dc2 100644 --- a/src/core/renderers/webgl/systems/TextureGCSystem.js +++ b/src/core/renderers/webgl/systems/TextureGCSystem.js @@ -56,7 +56,7 @@ run() { const tm = this.renderer.texture; - const managedTextures = tm._managedTextures; + const managedTextures = tm.managedTextures; let wasRemoved = false; for (let i = 0; i < managedTextures.length; i++) @@ -64,7 +64,7 @@ const texture = managedTextures[i]; // only supports non generated textures at the moment! - if (!texture._glRenderTargets && this.count - texture.touched > this.maxIdle) + if (!texture.frameBuffer && this.count - texture.touched > this.maxIdle) { tm.destroyTexture(texture, true); managedTextures[i] = null; diff --git a/src/core/textures/BaseTexture.js b/src/core/textures/BaseTexture.js index b8a4fcc..64945b6 100644 --- a/src/core/textures/BaseTexture.js +++ b/src/core/textures/BaseTexture.js @@ -111,6 +111,8 @@ this.setResource(resource); } + this.cacheId = null; + this.validate(); } @@ -120,7 +122,8 @@ this.resource = resource; - this.resource.load.then((resource) => { + this.resource.load + .then((resource) => { if(this.resource === resource) { @@ -143,6 +146,12 @@ } }) + .catch((reason)=>{ + + // failed to load - maybe resource was destroyed before it loaded. + console.warn(reason); + + }) this.resource.resourceUpdated.add(this); //calls resourceUpaded } @@ -189,6 +198,45 @@ } /** + * Destroys this base texture + * + */ + destroy() + { + // remove from the cache.. + + if (this.cacheId) + { + delete BaseTextureCache[this.cacheId]; + delete TextureCache[this.cacheId]; + + this.cacheId = null; + } + + // remove and destroy the resource + + if(this.resource) + { + this.resource.destroy(); + this.resource = null; + } + + // finally let the webGL renderer know.. + this.dispose() + } + + /** + * Frees the texture 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. + * + */ + dispose() + { + this.emit('dispose', this); + } + + /** * Helper function that creates a base texture based on the source you provide. * The source can be - image url, image element, canvas element. * @@ -221,6 +269,7 @@ if (!baseTexture) { baseTexture = new BaseTexture(source); + baseTexture.cacheId BaseTextureCache[cacheId] = baseTexture; } diff --git a/src/core/textures/resources/ImageResource.js b/src/core/textures/resources/ImageResource.js index aa1fe5e..17a8635 100644 --- a/src/core/textures/resources/ImageResource.js +++ b/src/core/textures/resources/ImageResource.js @@ -30,9 +30,18 @@ this.height = source.height; resolve(this); } + + source.onerror = () => { + reject('unable to load "' + source.src + '" resource cannot be found') + } }) } + destroy() + { + this.source.src = ''; + } + static from(url, crossorigin) { var image = new Image();