Allow WebGL wrapper operations during context loss.

This commit is contained in:
Ben Richards 2024-02-05 16:40:16 +13:00
parent 06d463e92e
commit 7ed40fdf7d
6 changed files with 113 additions and 41 deletions

View file

@ -81,7 +81,16 @@ var WebGLAttribLocationWrapper = new Class({
return;
}
this.webGLAttribLocation = this.gl.getAttribLocation(this.program.webGLProgram, this.name);
var gl = this.gl;
if (gl.isContextLost())
{
// GL state can't be updated right now.
// `createResource` will run when the context is restored.
return;
}
this.webGLAttribLocation = gl.getAttribLocation(this.program.webGLProgram, this.name);
},
/**

View file

@ -97,6 +97,14 @@ var WebGLBufferWrapper = new Class({
}
var gl = this.gl;
if (gl.isContextLost())
{
// GL state can't be updated right now.
// `createResource` will run when the context is restored.
return;
}
var bufferType = this.bufferType;
var webGLBuffer = gl.createBuffer();
@ -115,7 +123,11 @@ var WebGLBufferWrapper = new Class({
*/
destroy: function ()
{
this.gl.deleteBuffer(this.webGLBuffer);
var gl = this.gl;
if (!gl.isContextLost())
{
gl.deleteBuffer(this.webGLBuffer);
}
this.webGLBuffer = null;
this.initialDataOrSize = null;
this.gl = null;

View file

@ -113,6 +113,14 @@ var WebGLFramebufferWrapper = new Class({
createResource: function ()
{
var gl = this.gl;
if (gl.isContextLost())
{
// GL state can't be updated right now.
// `createResource` will run when the context is restored.
return;
}
var renderTexture = this.renderTexture;
var complete = 0;
var framebuffer = gl.createFramebuffer();
@ -159,32 +167,34 @@ var WebGLFramebufferWrapper = new Class({
var gl = this.gl;
gl.bindFramebuffer(gl.FRAMEBUFFER, this.webGLFramebuffer);
if (!gl.isContextLost())
{
gl.bindFramebuffer(gl.FRAMEBUFFER, this.webGLFramebuffer);
// Check for a color attachment and remove it
var colorAttachment = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
if (colorAttachment !== null)
{
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
gl.deleteTexture(colorAttachment);
}
// Check for a depth-stencil attachment and remove it
var depthStencilAttachment = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
if (depthStencilAttachment !== null)
{
gl.deleteRenderbuffer(depthStencilAttachment);
}
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.deleteFramebuffer(this.webGLFramebuffer);
}
this.renderTexture = null;
// Check for a color attachment and remove it
var colorAttachment = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
if (colorAttachment !== null)
{
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
gl.deleteTexture(colorAttachment);
}
// Check for a depth-stencil attachment and remove it
var depthStencilAttachment = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
if (depthStencilAttachment !== null)
{
gl.deleteRenderbuffer(depthStencilAttachment);
}
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.deleteFramebuffer(this.webGLFramebuffer);
this.webGLFramebuffer = null;
this.gl = null;
}

View file

@ -81,6 +81,13 @@ var WebGLProgramWrapper = new Class({
{
var gl = this.gl;
if (gl.isContextLost())
{
// GL state can't be updated right now.
// `createResource` will run when the context is restored.
return;
}
var program = gl.createProgram();
var vs = gl.createShader(gl.VERTEX_SHADER);
@ -132,7 +139,11 @@ var WebGLProgramWrapper = new Class({
return;
}
this.gl.deleteProgram(this.webGLProgram);
if (!this.gl.isContextLost())
{
this.gl.deleteProgram(this.webGLProgram);
}
this.webGLProgram = null;
this.gl = null;
}

View file

@ -210,6 +210,15 @@ var WebGLTextureWrapper = new Class({
*/
createResource: function ()
{
var gl = this.gl;
if (gl.isContextLost())
{
// GL state can't be updated right now.
// `createResource` will run when the context is restored.
return;
}
if (this.pixels instanceof WebGLTextureWrapper)
{
// Use the source texture directly.
@ -217,8 +226,6 @@ var WebGLTextureWrapper = new Class({
return;
}
var gl = this.gl;
var texture = gl.createTexture();
gl.activeTexture(gl.TEXTURE0);
@ -320,8 +327,21 @@ var WebGLTextureWrapper = new Class({
return;
}
// Assume that the source might change.
this.pixels = source;
this.width = width;
this.height = height;
this.flipY = flipY;
var gl = this.gl;
if (gl.isContextLost())
{
// GL state can't be updated right now.
// `createResource` will run when the context is restored.
return;
}
gl.activeTexture(gl.TEXTURE0);
var currentTexture = gl.getParameter(gl.TEXTURE_BINDING_2D);
@ -333,12 +353,6 @@ var WebGLTextureWrapper = new Class({
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
// Assume that the source might change.
this.pixels = source;
this.width = width;
this.height = height;
this.flipY = flipY;
// Restore previous texture bind.
if (currentTexture)
{
@ -365,8 +379,12 @@ var WebGLTextureWrapper = new Class({
{
// eslint-disable-next-line camelcase
this.__SPECTOR_Metadata = value;
// eslint-disable-next-line camelcase
this.webGLTexture.__SPECTOR_Metadata = value;
if (!this.gl.isContextLost())
{
// eslint-disable-next-line camelcase
this.webGLTexture.__SPECTOR_Metadata = value;
}
}
},
@ -383,10 +401,13 @@ var WebGLTextureWrapper = new Class({
return;
}
if (!(this.pixels instanceof WebGLTextureWrapper))
if (!this.gl.isContextLost())
{
// Do not delete a texture that belongs to another wrapper.
this.gl.deleteTexture(this.webGLTexture);
if (!(this.pixels instanceof WebGLTextureWrapper))
{
// Do not delete a texture that belongs to another wrapper.
this.gl.deleteTexture(this.webGLTexture);
}
}
this.pixels = null;

View file

@ -81,7 +81,16 @@ var WebGLUniformLocationWrapper = new Class({
return;
}
this.webGLUniformLocation = this.gl.getUniformLocation(this.program.webGLProgram, this.name);
var gl = this.gl;
if (gl.isContextLost())
{
// GL state can't be updated right now.
// `createResource` will run when the context is restored.
return;
}
this.webGLUniformLocation = gl.getUniformLocation(this.program.webGLProgram, this.name);
},
/**