Added support for webGL context loss

This commit is contained in:
Mat Groves 2014-01-01 21:35:55 +00:00
parent 1997071a9b
commit 53506da65e
7 changed files with 234 additions and 132 deletions

View file

@ -1004,7 +1004,7 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', {
if(this._mask)this._mask.isMask = false; if(this._mask)this._mask.isMask = false;
this._mask = value; this._mask = value;
this._mask.isMask = true; if(this._mask)this._mask.isMask = true;
} }
}); });
@ -4939,7 +4939,7 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias)
this.batchs = []; this.batchs = [];
var options = { this.options = {
alpha: this.transparent, alpha: this.transparent,
antialias:!!antialias, // SPEED UP?? antialias:!!antialias, // SPEED UP??
premultipliedAlpha:false, premultipliedAlpha:false,
@ -4948,11 +4948,11 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias)
//try 'experimental-webgl' //try 'experimental-webgl'
try { try {
this.gl = this.view.getContext('experimental-webgl', options); this.gl = this.view.getContext('experimental-webgl', this.options);
} catch (e) { } catch (e) {
//try 'webgl' //try 'webgl'
try { try {
this.gl = this.view.getContext('webgl', options); this.gl = this.view.getContext('webgl', this.options);
} catch (e2) { } catch (e2) {
// fail, not able to get a context // fail, not able to get a context
throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this); throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this);
@ -4960,7 +4960,7 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias)
} }
var gl = this.gl; var gl = this.gl;
gl.id = PIXI.WebGLRenderer.glContextId ++; this.glContextId = gl.id = PIXI.WebGLRenderer.glContextId ++;
if(!PIXI.blendModesWebGL) if(!PIXI.blendModesWebGL)
{ {
@ -5067,26 +5067,26 @@ PIXI.WebGLRenderer.prototype.render = function(stage)
} }
} }
/*
//can simulate context loss in Chrome like so: //can simulate context loss in Chrome like so:
// this.view.onmousedown = function(ev) { this.view.onmousedown = function(ev) {
// console.dir(this.gl.getSupportedExtensions()); console.dir(this.gl.getSupportedExtensions());
// var ext = ( var ext = (
// gl.getExtension("WEBGL_scompressed_texture_s3tc") gl.getExtension("WEBGL_scompressed_texture_s3tc")
// // gl.getExtension("WEBGL_compressed_texture_s3tc") || // gl.getExtension("WEBGL_compressed_texture_s3tc") ||
// // gl.getExtension("MOZ_WEBGL_compressed_texture_s3tc") || // gl.getExtension("MOZ_WEBGL_compressed_texture_s3tc") ||
// // gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc") // gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc")
// ); );
// console.dir(ext); console.dir(ext);
var loseCtx = this.gl.getExtension("WEBGL_lose_context");
// var loseCtx = this.gl.getExtension("WEBGL_lose_context"); console.log("killing context");
// console.log("killing context"); loseCtx.loseContext();
// loseCtx.loseContext(); setTimeout(function() {
console.log("restoring context...");
// setTimeout(function() { loseCtx.restoreContext();
// console.log("restoring context..."); }.bind(this), 1000);
// loseCtx.restoreContext(); }.bind(this);
// }.bind(this), 1000); */
// }.bind(this);
}; };
PIXI.WebGLRenderer.prototype.renderDisplayObject = function(displayObject, projection) PIXI.WebGLRenderer.prototype.renderDisplayObject = function(displayObject, projection)
@ -5288,28 +5288,50 @@ PIXI.WebGLRenderer.prototype.handleContextLost = function(event)
*/ */
PIXI.WebGLRenderer.prototype.handleContextRestored = function() PIXI.WebGLRenderer.prototype.handleContextRestored = function()
{ {
this.gl = this.view.getContext('experimental-webgl', {
alpha: true //try 'experimental-webgl'
}); try {
this.gl = this.view.getContext('experimental-webgl', this.options);
} catch (e) {
//try 'webgl'
try {
this.gl = this.view.getContext('webgl', this.options);
} catch (e2) {
// fail, not able to get a context
throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this);
}
}
this.initShaders(); var gl = this.gl;
gl.id = PIXI.WebGLRenderer.glContextId ++;
// need to set the context...
this.shaderManager.setContext(gl);
this.spriteBatch.setContext(gl);
this.maskManager.setContext(gl);
this.filterManager.setContext(gl);
this.renderSession.gl = this.gl;
gl.disable(gl.DEPTH_TEST);
gl.disable(gl.CULL_FACE);
gl.enable(gl.BLEND);
gl.colorMask(true, true, true, this.transparent);
this.gl.viewport(0, 0, this.width, this.height);
for(var key in PIXI.TextureCache) for(var key in PIXI.TextureCache)
{ {
var texture = PIXI.TextureCache[key].baseTexture; var texture = PIXI.TextureCache[key].baseTexture;
texture._glTexture = null; texture._glTextures = [];
PIXI.WebGLRenderer.updateTexture(texture);
} }
for (var i=0; i < this.batchs.length; i++)
{
this.batchs[i].restoreLostContext(this.gl);
this.batchs[i].dirty = true;
}
PIXI._restoreBatchs(this.gl);
this.contextLost = false; this.contextLost = false;
}; };
PIXI.WebGLRenderer.glContextId = 0; PIXI.WebGLRenderer.glContextId = 0;
@ -5320,9 +5342,15 @@ PIXI.WebGLRenderer.glContextId = 0;
PIXI.WebGLMaskManager = function(gl) PIXI.WebGLMaskManager = function(gl)
{ {
this.gl = gl;
this.maskStack = []; this.maskStack = [];
this.maskPosition = 0; this.maskPosition = 0;
this.setContext(gl);
};
PIXI.WebGLMaskManager.prototype.setContext = function(gl)
{
this.gl = gl;
}; };
PIXI.WebGLMaskManager.prototype.pushMask = function(maskData, renderSession) PIXI.WebGLMaskManager.prototype.pushMask = function(maskData, renderSession)
@ -5376,12 +5404,22 @@ PIXI.WebGLMaskManager.prototype.popMask = function(renderSession)
*/ */
PIXI.WebGLShaderManager = function(gl) PIXI.WebGLShaderManager = function(gl)
{
this.setContext(gl);
// the final one is used for the rendering strips
//this.stripShader = new PIXI.StripShader(gl);
};
PIXI.WebGLShaderManager.prototype.setContext = function(gl)
{ {
this.gl = gl; this.gl = gl;
// the next one is used for rendering primatives
this.primitiveShader = new PIXI.PrimitiveShader(gl);
// this shader is used for the default sprite rendering // this shader is used for the default sprite rendering
this.defaultShader = new PIXI.PixiShader(gl); this.defaultShader = new PIXI.PixiShader(gl);
//PIXI.defaultShader = this.defaultShader;
var shaderProgram = this.defaultShader.program; var shaderProgram = this.defaultShader.program;
@ -5391,14 +5429,8 @@ PIXI.WebGLShaderManager = function(gl)
gl.enableVertexAttribArray(this.defaultShader.colorAttribute); gl.enableVertexAttribArray(this.defaultShader.colorAttribute);
gl.enableVertexAttribArray(this.defaultShader.aTextureCoord); gl.enableVertexAttribArray(this.defaultShader.aTextureCoord);
// the next one is used for rendering primatives
this.primitiveShader = new PIXI.PrimitiveShader(gl); }
// the final one is used for the rendering strips
//this.stripShader = new PIXI.StripShader(gl);
};
PIXI.WebGLShaderManager.prototype.activatePrimitiveShader = function() PIXI.WebGLShaderManager.prototype.activatePrimitiveShader = function()
{ {
@ -5439,25 +5471,17 @@ PIXI.WebGLShaderManager.prototype.deactivatePrimitiveShader = function()
PIXI.WebGLSpriteBatch = function(gl) PIXI.WebGLSpriteBatch = function(gl)
{ {
this.gl = gl;
// create a couple of buffers
this.vertexBuffer = gl.createBuffer();
this.indexBuffer = gl.createBuffer();
this.size = 2000; this.size = 2000;
this.vertSize = 6; this.vertSize = 6;
// 65535 is max index, so 65535 / 6 = 10922.
//the total number of floats in our batch //the total number of floats in our batch
var numVerts = this.size * 4 * this.vertSize; var numVerts = this.size * 4 * this.vertSize;
//the total number of indices in our batch //the total number of indices in our batch
var numIndices = this.size * 6; var numIndices = this.size * 6;
//vertex data
//vertex data
this.vertices = new Float32Array(numVerts); this.vertices = new Float32Array(numVerts);
//index data //index data
this.indices = new Uint16Array(numIndices); this.indices = new Uint16Array(numIndices);
@ -5474,6 +5498,29 @@ PIXI.WebGLSpriteBatch = function(gl)
this.indices[i + 5] = j + 3; this.indices[i + 5] = j + 3;
} }
this.drawing = false;
this.currentBatchSize = 0;
this.currentBaseTexture = null;
this.setContext(gl);
};
PIXI.WebGLSpriteBatch.prototype.setContext = function(gl)
{
this.gl = gl;
// create a couple of buffers
this.vertexBuffer = gl.createBuffer();
this.indexBuffer = gl.createBuffer();
// 65535 is max index, so 65535 / 6 = 10922.
//the total number of floats in our batch
var numVerts = this.size * 4 * this.vertSize;
//the total number of indices in our batch
var numIndices = this.size * 6;
//upload the index data //upload the index data
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);
@ -5481,10 +5528,8 @@ PIXI.WebGLSpriteBatch = function(gl)
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.vertices, gl.DYNAMIC_DRAW); gl.bufferData(gl.ARRAY_BUFFER, this.vertices, gl.DYNAMIC_DRAW);
this.drawing = false; this.currentBlendMode = 99999;
this.currentBatchSize = 0; }
this.currentBaseTexture = null;
};
PIXI.WebGLSpriteBatch.prototype.begin = function(renderSession) PIXI.WebGLSpriteBatch.prototype.begin = function(renderSession)
{ {
@ -5805,20 +5850,26 @@ PIXI.WebGLSpriteBatch.prototype.setBlendMode = function(blendMode)
PIXI.WebGLFilterManager = function(gl, transparent) PIXI.WebGLFilterManager = function(gl, transparent)
{ {
this.gl = gl;
this.transparent = transparent; this.transparent = transparent;
this.filterStack = []; this.filterStack = [];
this.texturePool = [];
this.offsetX = 0; this.offsetX = 0;
this.offsetY = 0; this.offsetY = 0;
this.initShaderBuffers(); this.setContext(gl);
}; };
// API // API
PIXI.WebGLFilterManager.prototype.setContext = function(gl)
{
this.gl = gl;
this.texturePool = [];
this.initShaderBuffers();
}
PIXI.WebGLFilterManager.prototype.begin = function(renderSession, buffer) PIXI.WebGLFilterManager.prototype.begin = function(renderSession, buffer)
{ {
this.renderSession = renderSession; this.renderSession = renderSession;

View file

@ -307,7 +307,7 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', {
if(this._mask)this._mask.isMask = false; if(this._mask)this._mask.isMask = false;
this._mask = value; this._mask = value;
this._mask.isMask = true; if(this._mask)this._mask.isMask = true;
} }
}); });

View file

@ -48,7 +48,7 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias)
this.batchs = []; this.batchs = [];
var options = { this.options = {
alpha: this.transparent, alpha: this.transparent,
antialias:!!antialias, // SPEED UP?? antialias:!!antialias, // SPEED UP??
premultipliedAlpha:false, premultipliedAlpha:false,
@ -57,11 +57,11 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias)
//try 'experimental-webgl' //try 'experimental-webgl'
try { try {
this.gl = this.view.getContext('experimental-webgl', options); this.gl = this.view.getContext('experimental-webgl', this.options);
} catch (e) { } catch (e) {
//try 'webgl' //try 'webgl'
try { try {
this.gl = this.view.getContext('webgl', options); this.gl = this.view.getContext('webgl', this.options);
} catch (e2) { } catch (e2) {
// fail, not able to get a context // fail, not able to get a context
throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this); throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this);
@ -69,7 +69,7 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias)
} }
var gl = this.gl; var gl = this.gl;
gl.id = PIXI.WebGLRenderer.glContextId ++; this.glContextId = gl.id = PIXI.WebGLRenderer.glContextId ++;
if(!PIXI.blendModesWebGL) if(!PIXI.blendModesWebGL)
{ {
@ -176,26 +176,26 @@ PIXI.WebGLRenderer.prototype.render = function(stage)
} }
} }
/*
//can simulate context loss in Chrome like so: //can simulate context loss in Chrome like so:
// this.view.onmousedown = function(ev) { this.view.onmousedown = function(ev) {
// console.dir(this.gl.getSupportedExtensions()); console.dir(this.gl.getSupportedExtensions());
// var ext = ( var ext = (
// gl.getExtension("WEBGL_scompressed_texture_s3tc") gl.getExtension("WEBGL_scompressed_texture_s3tc")
// // gl.getExtension("WEBGL_compressed_texture_s3tc") || // gl.getExtension("WEBGL_compressed_texture_s3tc") ||
// // gl.getExtension("MOZ_WEBGL_compressed_texture_s3tc") || // gl.getExtension("MOZ_WEBGL_compressed_texture_s3tc") ||
// // gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc") // gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc")
// ); );
// console.dir(ext); console.dir(ext);
var loseCtx = this.gl.getExtension("WEBGL_lose_context");
// var loseCtx = this.gl.getExtension("WEBGL_lose_context"); console.log("killing context");
// console.log("killing context"); loseCtx.loseContext();
// loseCtx.loseContext(); setTimeout(function() {
console.log("restoring context...");
// setTimeout(function() { loseCtx.restoreContext();
// console.log("restoring context..."); }.bind(this), 1000);
// loseCtx.restoreContext(); }.bind(this);
// }.bind(this), 1000); */
// }.bind(this);
}; };
PIXI.WebGLRenderer.prototype.renderDisplayObject = function(displayObject, projection) PIXI.WebGLRenderer.prototype.renderDisplayObject = function(displayObject, projection)
@ -397,28 +397,50 @@ PIXI.WebGLRenderer.prototype.handleContextLost = function(event)
*/ */
PIXI.WebGLRenderer.prototype.handleContextRestored = function() PIXI.WebGLRenderer.prototype.handleContextRestored = function()
{ {
this.gl = this.view.getContext('experimental-webgl', {
alpha: true //try 'experimental-webgl'
}); try {
this.gl = this.view.getContext('experimental-webgl', this.options);
} catch (e) {
//try 'webgl'
try {
this.gl = this.view.getContext('webgl', this.options);
} catch (e2) {
// fail, not able to get a context
throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this);
}
}
this.initShaders(); var gl = this.gl;
gl.id = PIXI.WebGLRenderer.glContextId ++;
// need to set the context...
this.shaderManager.setContext(gl);
this.spriteBatch.setContext(gl);
this.maskManager.setContext(gl);
this.filterManager.setContext(gl);
this.renderSession.gl = this.gl;
gl.disable(gl.DEPTH_TEST);
gl.disable(gl.CULL_FACE);
gl.enable(gl.BLEND);
gl.colorMask(true, true, true, this.transparent);
this.gl.viewport(0, 0, this.width, this.height);
for(var key in PIXI.TextureCache) for(var key in PIXI.TextureCache)
{ {
var texture = PIXI.TextureCache[key].baseTexture; var texture = PIXI.TextureCache[key].baseTexture;
texture._glTexture = null; texture._glTextures = [];
PIXI.WebGLRenderer.updateTexture(texture);
} }
for (var i=0; i < this.batchs.length; i++)
{
this.batchs[i].restoreLostContext(this.gl);
this.batchs[i].dirty = true;
}
PIXI._restoreBatchs(this.gl);
this.contextLost = false; this.contextLost = false;
}; };
PIXI.WebGLRenderer.glContextId = 0; PIXI.WebGLRenderer.glContextId = 0;

View file

@ -5,20 +5,26 @@
PIXI.WebGLFilterManager = function(gl, transparent) PIXI.WebGLFilterManager = function(gl, transparent)
{ {
this.gl = gl;
this.transparent = transparent; this.transparent = transparent;
this.filterStack = []; this.filterStack = [];
this.texturePool = [];
this.offsetX = 0; this.offsetX = 0;
this.offsetY = 0; this.offsetY = 0;
this.initShaderBuffers(); this.setContext(gl);
}; };
// API // API
PIXI.WebGLFilterManager.prototype.setContext = function(gl)
{
this.gl = gl;
this.texturePool = [];
this.initShaderBuffers();
}
PIXI.WebGLFilterManager.prototype.begin = function(renderSession, buffer) PIXI.WebGLFilterManager.prototype.begin = function(renderSession, buffer)
{ {
this.renderSession = renderSession; this.renderSession = renderSession;

View file

@ -4,9 +4,15 @@
PIXI.WebGLMaskManager = function(gl) PIXI.WebGLMaskManager = function(gl)
{ {
this.gl = gl;
this.maskStack = []; this.maskStack = [];
this.maskPosition = 0; this.maskPosition = 0;
this.setContext(gl);
};
PIXI.WebGLMaskManager.prototype.setContext = function(gl)
{
this.gl = gl;
}; };
PIXI.WebGLMaskManager.prototype.pushMask = function(maskData, renderSession) PIXI.WebGLMaskManager.prototype.pushMask = function(maskData, renderSession)

View file

@ -3,12 +3,22 @@
*/ */
PIXI.WebGLShaderManager = function(gl) PIXI.WebGLShaderManager = function(gl)
{
this.setContext(gl);
// the final one is used for the rendering strips
//this.stripShader = new PIXI.StripShader(gl);
};
PIXI.WebGLShaderManager.prototype.setContext = function(gl)
{ {
this.gl = gl; this.gl = gl;
// the next one is used for rendering primatives
this.primitiveShader = new PIXI.PrimitiveShader(gl);
// this shader is used for the default sprite rendering // this shader is used for the default sprite rendering
this.defaultShader = new PIXI.PixiShader(gl); this.defaultShader = new PIXI.PixiShader(gl);
//PIXI.defaultShader = this.defaultShader;
var shaderProgram = this.defaultShader.program; var shaderProgram = this.defaultShader.program;
@ -18,14 +28,8 @@ PIXI.WebGLShaderManager = function(gl)
gl.enableVertexAttribArray(this.defaultShader.colorAttribute); gl.enableVertexAttribArray(this.defaultShader.colorAttribute);
gl.enableVertexAttribArray(this.defaultShader.aTextureCoord); gl.enableVertexAttribArray(this.defaultShader.aTextureCoord);
// the next one is used for rendering primatives
this.primitiveShader = new PIXI.PrimitiveShader(gl); }
// the final one is used for the rendering strips
//this.stripShader = new PIXI.StripShader(gl);
};
PIXI.WebGLShaderManager.prototype.activatePrimitiveShader = function() PIXI.WebGLShaderManager.prototype.activatePrimitiveShader = function()
{ {

View file

@ -10,25 +10,17 @@
PIXI.WebGLSpriteBatch = function(gl) PIXI.WebGLSpriteBatch = function(gl)
{ {
this.gl = gl;
// create a couple of buffers
this.vertexBuffer = gl.createBuffer();
this.indexBuffer = gl.createBuffer();
this.size = 2000; this.size = 2000;
this.vertSize = 6; this.vertSize = 6;
// 65535 is max index, so 65535 / 6 = 10922.
//the total number of floats in our batch //the total number of floats in our batch
var numVerts = this.size * 4 * this.vertSize; var numVerts = this.size * 4 * this.vertSize;
//the total number of indices in our batch //the total number of indices in our batch
var numIndices = this.size * 6; var numIndices = this.size * 6;
//vertex data
//vertex data
this.vertices = new Float32Array(numVerts); this.vertices = new Float32Array(numVerts);
//index data //index data
this.indices = new Uint16Array(numIndices); this.indices = new Uint16Array(numIndices);
@ -45,6 +37,29 @@ PIXI.WebGLSpriteBatch = function(gl)
this.indices[i + 5] = j + 3; this.indices[i + 5] = j + 3;
} }
this.drawing = false;
this.currentBatchSize = 0;
this.currentBaseTexture = null;
this.setContext(gl);
};
PIXI.WebGLSpriteBatch.prototype.setContext = function(gl)
{
this.gl = gl;
// create a couple of buffers
this.vertexBuffer = gl.createBuffer();
this.indexBuffer = gl.createBuffer();
// 65535 is max index, so 65535 / 6 = 10922.
//the total number of floats in our batch
var numVerts = this.size * 4 * this.vertSize;
//the total number of indices in our batch
var numIndices = this.size * 6;
//upload the index data //upload the index data
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);
@ -52,10 +67,8 @@ PIXI.WebGLSpriteBatch = function(gl)
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.vertices, gl.DYNAMIC_DRAW); gl.bufferData(gl.ARRAY_BUFFER, this.vertices, gl.DYNAMIC_DRAW);
this.drawing = false; this.currentBlendMode = 99999;
this.currentBatchSize = 0; }
this.currentBaseTexture = null;
};
PIXI.WebGLSpriteBatch.prototype.begin = function(renderSession) PIXI.WebGLSpriteBatch.prototype.begin = function(renderSession)
{ {