From 50516e3d342e7faeb86ddf936f60a63ebb1ca7e1 Mon Sep 17 00:00:00 2001 From: photonstorm Date: Mon, 3 Aug 2015 14:33:12 +0100 Subject: [PATCH] Testing CanvasPool. --- build/config.php | 2 + src/gameobjects/Text.js | 24 +-- src/input/Input.js | 6 +- src/pixi/extras/TilingSprite.js | 2 + src/pixi/renderers/canvas/CanvasRenderer.js | 4 +- .../renderers/canvas/utils/CanvasBuffer.js | 12 +- .../renderers/canvas/utils/CanvasTinter.js | 2 +- src/pixi/renderers/webgl/WebGLRenderer.js | 4 +- src/pixi/textures/BaseTexture.js | 8 +- src/pixi/textures/Texture.js | 1 - src/pixi/utils/CanvasPool.js | 145 ++++++++++++++++++ src/pixi/utils/Utils.js | 7 +- src/system/Device.js | 4 +- 13 files changed, 194 insertions(+), 27 deletions(-) create mode 100644 src/pixi/utils/CanvasPool.js diff --git a/build/config.php b/build/config.php index 54a384e08..3a1e3bb15 100644 --- a/build/config.php +++ b/build/config.php @@ -56,6 +56,7 @@ + @@ -73,6 +74,7 @@ + diff --git a/src/gameobjects/Text.js b/src/gameobjects/Text.js index aae151e5e..84500c802 100644 --- a/src/gameobjects/Text.js +++ b/src/gameobjects/Text.js @@ -73,7 +73,7 @@ Phaser.Text = function (game, x, y, text, style) { /** * @property {HTMLCanvasElement} canvas - The canvas element that the text is rendered. */ - this.canvas = document.createElement('canvas'); + this.canvas = PIXI.CanvasPool.create(this); /** * @property {HTMLCanvasElement} context - The context of the canvas element that the text is rendered to. @@ -201,15 +201,17 @@ Phaser.Text.prototype.destroy = function (destroyChildren) { this.texture.destroy(true); - if (this.canvas && this.canvas.parentNode) - { - this.canvas.parentNode.removeChild(this.canvas); - } - else - { - this.canvas = null; - this.context = null; - } + PIXI.CanvasPool.remove(this); + + // if (this.canvas && this.canvas.parentNode) + // { + // this.canvas.parentNode.removeChild(this.canvas); + // } + // else + // { + // this.canvas = null; + // this.context = null; + // } Phaser.Component.Destroy.prototype.destroy.call(this, destroyChildren); @@ -1973,5 +1975,5 @@ Object.defineProperty(Phaser.Text.prototype, 'height', { Phaser.Text.fontPropertiesCache = {}; -Phaser.Text.fontPropertiesCanvas = document.createElement('canvas'); +Phaser.Text.fontPropertiesCanvas = PIXI.CanvasPool.create(Phaser.Text.fontPropertiesCanvas); Phaser.Text.fontPropertiesContext = Phaser.Text.fontPropertiesCanvas.getContext('2d'); diff --git a/src/input/Input.js b/src/input/Input.js index 604ea77a0..2d9056d99 100644 --- a/src/input/Input.js +++ b/src/input/Input.js @@ -406,9 +406,7 @@ Phaser.Input.prototype = { this.activePointer = this.mousePointer; - this.hitCanvas = document.createElement('canvas'); - this.hitCanvas.width = 1; - this.hitCanvas.height = 1; + this.hitCanvas = PIXI.CanvasPool.create(this, 1, 1); this.hitContext = this.hitCanvas.getContext('2d'); this.mouse.start(); @@ -454,6 +452,8 @@ Phaser.Input.prototype = { this.moveCallbacks = []; + PIXI.CanvasPool.remove(this); + this.game.canvas.removeEventListener('click', this._onClickTrampoline); }, diff --git a/src/pixi/extras/TilingSprite.js b/src/pixi/extras/TilingSprite.js index 03b6c862a..d75f26811 100644 --- a/src/pixi/extras/TilingSprite.js +++ b/src/pixi/extras/TilingSprite.js @@ -497,6 +497,8 @@ PIXI.TilingSprite.prototype.getBounds = function() PIXI.TilingSprite.prototype.destroy = function () { + this.canvasBuffer.destroy(); + PIXI.Sprite.prototype.destroy.call(this); this.tileScale = null; diff --git a/src/pixi/renderers/canvas/CanvasRenderer.js b/src/pixi/renderers/canvas/CanvasRenderer.js index 985b082a8..c30e5dc83 100644 --- a/src/pixi/renderers/canvas/CanvasRenderer.js +++ b/src/pixi/renderers/canvas/CanvasRenderer.js @@ -107,14 +107,14 @@ PIXI.CanvasRenderer = function(width, height, options) * @property view * @type HTMLCanvasElement */ - this.view = options.view || document.createElement( "canvas" ); + this.view = options.view || PIXI.CanvasPool.create(this, this.width, this.height); /** * The canvas 2d context that everything is drawn with * @property context * @type CanvasRenderingContext2D */ - this.context = this.view.getContext( "2d", { alpha: this.transparent } ); + this.context = this.view.getContext("2d", { alpha: this.transparent } ); /** * Boolean flag controlling canvas refresh. diff --git a/src/pixi/renderers/canvas/utils/CanvasBuffer.js b/src/pixi/renderers/canvas/utils/CanvasBuffer.js index b53d8510d..c3981003d 100644 --- a/src/pixi/renderers/canvas/utils/CanvasBuffer.js +++ b/src/pixi/renderers/canvas/utils/CanvasBuffer.js @@ -34,7 +34,7 @@ PIXI.CanvasBuffer = function(width, height) * @property canvas * @type HTMLCanvasElement */ - this.canvas = document.createElement("canvas"); + this.canvas = PIXI.CanvasPool.create(this, this.width, this.height); /** * A CanvasRenderingContext2D object representing a two-dimensional rendering context. @@ -74,3 +74,13 @@ PIXI.CanvasBuffer.prototype.resize = function(width, height) this.width = this.canvas.width = width; this.height = this.canvas.height = height; }; + +/** + * Frees the canvas up for use again. + * + * @method destroy + */ +PIXI.CanvasBuffer.prototype.destroy = function() +{ + PIXI.CanvasPool.remove(this); +}; diff --git a/src/pixi/renderers/canvas/utils/CanvasTinter.js b/src/pixi/renderers/canvas/utils/CanvasTinter.js index 59bb5d141..72e572a06 100644 --- a/src/pixi/renderers/canvas/utils/CanvasTinter.js +++ b/src/pixi/renderers/canvas/utils/CanvasTinter.js @@ -21,7 +21,7 @@ PIXI.CanvasTinter = function() {}; */ PIXI.CanvasTinter.getTintedTexture = function(sprite, color) { - var canvas = sprite.tintedTexture || document.createElement("canvas"); + var canvas = sprite.tintedTexture || PIXI.CanvasPool.create(this); PIXI.CanvasTinter.tintMethod(sprite.texture, color, canvas); diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js index a3e130169..979266a25 100644 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ b/src/pixi/renderers/webgl/WebGLRenderer.js @@ -119,7 +119,7 @@ PIXI.WebGLRenderer = function(width, height, options) * @property view * @type HTMLCanvasElement */ - this.view = options.view || document.createElement('canvas'); + this.view = options.view || PIXI.CanvasPool.create(this, this.width, this.height); /** * @property _contextOptions @@ -445,6 +445,8 @@ PIXI.WebGLRenderer.prototype.destroy = function() this.gl = null; this.renderSession = null; + PIXI.CanvasPool.remove(this); + PIXI.instances[this.glContextId] = null; PIXI.WebGLRenderer.glContextId--; diff --git a/src/pixi/textures/BaseTexture.js b/src/pixi/textures/BaseTexture.js index e8b442e23..47314993f 100644 --- a/src/pixi/textures/BaseTexture.js +++ b/src/pixi/textures/BaseTexture.js @@ -171,6 +171,8 @@ PIXI.BaseTexture.prototype.destroy = function() } else if (this.source && this.source._pixiId) { + PIXI.CanvasPool.removeByCanvas(this.source); + delete PIXI.BaseTextureCache[this.source._pixiId]; } @@ -254,7 +256,7 @@ PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin, scaleMode) { // new Image() breaks tex loading in some versions of Chrome. // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); + var image = new Image(); if (crossorigin) { @@ -287,7 +289,7 @@ PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin, scaleMode) */ PIXI.BaseTexture.fromCanvas = function(canvas, scaleMode) { - if(!canvas._pixiId) + if (!canvas._pixiId) { canvas._pixiId = 'canvas_' + PIXI.TextureCacheIdGenerator++; } @@ -304,7 +306,7 @@ PIXI.BaseTexture.fromCanvas = function(canvas, scaleMode) var baseTexture = PIXI.BaseTextureCache[canvas._pixiId]; - if(!baseTexture) + if (!baseTexture) { baseTexture = new PIXI.BaseTexture(canvas, scaleMode); PIXI.BaseTextureCache[canvas._pixiId] = baseTexture; diff --git a/src/pixi/textures/Texture.js b/src/pixi/textures/Texture.js index 08f7c17a6..52acbc9c2 100644 --- a/src/pixi/textures/Texture.js +++ b/src/pixi/textures/Texture.js @@ -305,7 +305,6 @@ PIXI.Texture.fromCanvas = function(canvas, scaleMode) var baseTexture = PIXI.BaseTexture.fromCanvas(canvas, scaleMode); return new PIXI.Texture(baseTexture); - }; /** diff --git a/src/pixi/utils/CanvasPool.js b/src/pixi/utils/CanvasPool.js new file mode 100644 index 000000000..8205d1412 --- /dev/null +++ b/src/pixi/utils/CanvasPool.js @@ -0,0 +1,145 @@ +/** +* @author Richard Davey +* @copyright 2015 Photon Storm Ltd. +* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} +*/ + +/** +* +* +* @class PIXI.CanvasPool +* @static +*/ +PIXI.CanvasPool = { + + /** + * + * + * @method PIXI.CanvasPool.create + * @static + * @param {any} parent - The parent of the canvas element. + * @param {number} width - The width of the canvas element. + * @param {number} height - The height of the canvas element. + * @return {HTMLCanvasElement} The canvas element. + */ + create: function (parent, width, height) { + + var idx = PIXI.CanvasPool.getFirst(); + var canvas; + + if (idx === -1) + { + var container = { + parent: parent, + canvas: document.createElement("canvas") + } + + PIXI.CanvasPool.pool.push(container); + + canvas = container.canvas; + + console.log('CanvasPool created', PIXI.CanvasPool.pool.length); + } + else + { + PIXI.CanvasPool.pool[idx].parent = parent; + + canvas = PIXI.CanvasPool.pool[idx].canvas; + + console.log('CanvasPool recycled', idx); + } + + if (width !== undefined) + { + canvas.width = width; + canvas.height = height; + canvas.clearRect(0, 0, width, height); + } + + return canvas; + + }, + + getFirst: function () { + + var pool = PIXI.CanvasPool.pool; + + for (var i = 0; i < pool.length; i++) + { + if (pool[i].parent === null) + { + return i; + } + } + + return -1; + + }, + + remove: function (parent) { + + var pool = PIXI.CanvasPool.pool; + + for (var i = 0; i < pool.length; i++) + { + if (pool[i].parent === parent) + { + pool[i].parent = null; + + console.log('CanvasPool removed', i); + } + } + + }, + + removeByCanvas: function (canvas) { + + var pool = PIXI.CanvasPool.pool; + + for (var i = 0; i < pool.length; i++) + { + if (pool[i].canvas === canvas) + { + pool[i].parent = null; + } + } + + }, + + getTotal: function () { + + var pool = PIXI.CanvasPool.pool; + var c = 0; + + for (var i = 0; i < pool.length; i++) + { + if (pool[i].parent !== null) + { + c++; + } + } + + return c; + + }, + + getFree: function () { + + var pool = PIXI.CanvasPool.pool; + var c = 0; + + for (var i = 0; i < pool.length; i++) + { + if (pool[i].parent === null) + { + c++; + } + } + + return c; + + } + +}; + +PIXI.CanvasPool.pool = []; diff --git a/src/pixi/utils/Utils.js b/src/pixi/utils/Utils.js index b8c177e51..aca190bfe 100644 --- a/src/pixi/utils/Utils.js +++ b/src/pixi/utils/Utils.js @@ -41,9 +41,7 @@ PIXI.canUseNewCanvasBlendModes = function() var yellow = new Image(); yellow.src = pngHead + '/wCKxvRF' + pngEnd; - var canvas = document.createElement('canvas'); - canvas.width = 6; - canvas.height = 1; + var canvas = PIXI.CanvasPool.create(this, 6, 1); var context = canvas.getContext('2d'); context.globalCompositeOperation = 'multiply'; context.drawImage(magenta, 0, 0); @@ -56,7 +54,10 @@ PIXI.canUseNewCanvasBlendModes = function() var data = context.getImageData(2,0,1,1).data; + PIXI.CanvasPool.remove(this); + return (data[0] === 255 && data[1] === 0 && data[2] === 0); + }; /** diff --git a/src/system/Device.js b/src/system/Device.js index da0592908..873755b79 100644 --- a/src/system/Device.js +++ b/src/system/Device.js @@ -1130,7 +1130,7 @@ Phaser.Device._initialize = function () { return false; } - var elem = document.createElement('canvas'); + var elem = PIXI.CanvasPool.create(this, 1, 1); var ctx = elem.getContext('2d'); if (!ctx) @@ -1140,6 +1140,8 @@ Phaser.Device._initialize = function () { var image = ctx.createImageData(1, 1); + PIXI.CanvasPool.remove(this); + return image.data instanceof Uint8ClampedArray; }