Skip to content

Commit 8eb34f9

Browse files
committed
WebGL context loss and restoration is now handled directly by Phaser.
Cache.clearGLTextures empties out all of the GL Textures from Images stored in the cache. This is called automatically when the WebGL context is lost and then restored.
1 parent 000afb7 commit 8eb34f9

4 files changed

Lines changed: 66 additions & 61 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,8 @@ For the full list of p2 additions please read [their change log](https://github.
411411
* World.stateChange is a new method that is called whenever the state changes or restarts. It resets the world x/y coordinates back to zero and then resets the Camera.
412412
* All undefined argument checks were changed from `if (typeof x === 'undefined')` to `if (x === undefined)` removing the typeof check and saving some bytes across the codebase in the process.
413413
* Text.updateText will now check the width and height values of the Text canvas and if either are zero it sets `Text.renderable = false` to avoid throwing WebGL texture binding errors.
414+
* WebGL context loss and restoration is now handled directly by Phaser.
415+
* Cache.clearGLTextures empties out all of the GL Textures from Images stored in the cache. This is called automatically when the WebGL context is lost and then restored.
414416

415417
### Bug Fixes
416418

src/core/Game.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,9 @@ Phaser.Game.prototype = {
733733
"antialias": this.antialias,
734734
"preserveDrawingBuffer": this.preserveDrawingBuffer });
735735
this.context = null;
736+
737+
this.canvas.addEventListener('webglcontextlost', this.contextLost.bind(this), false);
738+
this.canvas.addEventListener('webglcontextrestored', this.contextRestored.bind(this), false);
736739
}
737740

738741
if (this.renderType !== Phaser.HEADLESS)
@@ -745,6 +748,38 @@ Phaser.Game.prototype = {
745748

746749
},
747750

751+
/**
752+
* Handles WebGL context loss.
753+
*
754+
* @method Phaser.Game#contextLost
755+
* @private
756+
* @param {Event} event - The webglcontextlost event.
757+
*/
758+
contextLost: function (event) {
759+
760+
event.preventDefault();
761+
762+
this.renderer.contextLost = true;
763+
764+
},
765+
766+
/**
767+
* Handles WebGL context restoration.
768+
*
769+
* @method Phaser.Game#contextRestored
770+
* @private
771+
* @param {Event} event - The webglcontextrestored event.
772+
*/
773+
contextRestored: function (event) {
774+
775+
this.renderer.initContext();
776+
777+
this.cache.clearGLTextures();
778+
779+
this.renderer.contextLost = false;
780+
781+
},
782+
748783
/**
749784
* The core game loop.
750785
*

src/loader/Cache.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,6 +1871,22 @@ Phaser.Cache.prototype = {
18711871

18721872
},
18731873

1874+
/**
1875+
* Empties out all of the GL Textures from Images stored in the cache.
1876+
* This is called automatically when the WebGL context is lost and then restored.
1877+
*
1878+
* @method Phaser.Cache#clearGLTextures
1879+
* @protected
1880+
*/
1881+
clearGLTextures: function () {
1882+
1883+
for (var key in this.cache.image)
1884+
{
1885+
this.cache.image[key].base._glTextures = [];
1886+
}
1887+
1888+
},
1889+
18741890
/**
18751891
* Resolves a URL to its absolute form and stores it in Cache._urlMap as long as Cache.autoResolveURL is set to `true`.
18761892
* This is then looked-up by the Cache.getURL and Cache.checkURL calls.

src/pixi/renderers/webgl/WebGLRenderer.js

Lines changed: 13 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -119,24 +119,7 @@ PIXI.WebGLRenderer = function(width, height, options)
119119
* @property view
120120
* @type HTMLCanvasElement
121121
*/
122-
this.view = options.view || document.createElement( 'canvas' );
123-
124-
// deal with losing context..
125-
126-
/**
127-
* @property contextLostBound
128-
* @type Function
129-
*/
130-
this.contextLostBound = this.handleContextLost.bind(this);
131-
132-
/**
133-
* @property contextRestoredBound
134-
* @type Function
135-
*/
136-
this.contextRestoredBound = this.handleContextRestored.bind(this);
137-
138-
this.view.addEventListener('webglcontextlost', this.contextLostBound, false);
139-
this.view.addEventListener('webglcontextrestored', this.contextRestoredBound, false);
122+
this.view = options.view || document.createElement('canvas');
140123

141124
/**
142125
* @property _contextOptions
@@ -390,20 +373,27 @@ PIXI.WebGLRenderer.prototype.resize = function(width, height)
390373
*/
391374
PIXI.WebGLRenderer.prototype.updateTexture = function(texture)
392375
{
393-
if(!texture.hasLoaded )return;
376+
if (!texture.hasLoaded)
377+
{
378+
return;
379+
}
394380

395381
var gl = this.gl;
396382

397-
if(!texture._glTextures[gl.id])texture._glTextures[gl.id] = gl.createTexture();
383+
if (!texture._glTextures[gl.id])
384+
{
385+
texture._glTextures[gl.id] = gl.createTexture();
386+
}
398387

399388
gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]);
400389

401390
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha);
391+
402392
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source);
403393

404394
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST);
405395

406-
if(texture.mipmap && PIXI.isPowerOfTwo(texture.width, texture.height))
396+
if (texture.mipmap && PIXI.isPowerOfTwo(texture.width, texture.height))
407397
{
408398
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST);
409399
gl.generateMipmap(gl.TEXTURE_2D);
@@ -413,8 +403,7 @@ PIXI.WebGLRenderer.prototype.updateTexture = function(texture)
413403
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST);
414404
}
415405

416-
// reguler...
417-
if(!texture._powerOf2)
406+
if (!texture._powerOf2)
418407
{
419408
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
420409
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
@@ -428,40 +417,7 @@ PIXI.WebGLRenderer.prototype.updateTexture = function(texture)
428417
texture._dirty[gl.id] = false;
429418

430419
return texture._glTextures[gl.id];
431-
};
432-
433-
/**
434-
* Handles a lost webgl context
435-
*
436-
* @method handleContextLost
437-
* @param event {Event}
438-
* @private
439-
*/
440-
PIXI.WebGLRenderer.prototype.handleContextLost = function(event)
441-
{
442-
event.preventDefault();
443-
this.contextLost = true;
444-
};
445420

446-
/**
447-
* Handles a restored webgl context
448-
*
449-
* @method handleContextRestored
450-
* @param event {Event}
451-
* @private
452-
*/
453-
PIXI.WebGLRenderer.prototype.handleContextRestored = function()
454-
{
455-
this.initContext();
456-
457-
// empty all the ol gl textures as they are useless now
458-
for(var key in PIXI.TextureCache)
459-
{
460-
var texture = PIXI.TextureCache[key].baseTexture;
461-
texture._glTextures = [];
462-
}
463-
464-
this.contextLost = false;
465421
};
466422

467423
/**
@@ -471,10 +427,6 @@ PIXI.WebGLRenderer.prototype.handleContextRestored = function()
471427
*/
472428
PIXI.WebGLRenderer.prototype.destroy = function()
473429
{
474-
// remove listeners
475-
this.view.removeEventListener('webglcontextlost', this.contextLostBound);
476-
this.view.removeEventListener('webglcontextrestored', this.contextRestoredBound);
477-
478430
PIXI.glContexts[this.glContextId] = null;
479431

480432
this.projection = null;
@@ -507,7 +459,7 @@ PIXI.WebGLRenderer.prototype.mapBlendModes = function()
507459
{
508460
var gl = this.gl;
509461

510-
if(!PIXI.blendModesWebGL)
462+
if (!PIXI.blendModesWebGL)
511463
{
512464
PIXI.blendModesWebGL = [];
513465

0 commit comments

Comments
 (0)