Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebGLObject creation is now infallible, and starts Lost iff context Lost. #3642

Merged
merged 5 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion extensions/EXT_disjoint_timer_query/extension.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ interface EXT_disjoint_timer_query {
const GLenum TIMESTAMP_EXT = 0x8E28;
const GLenum GPU_DISJOINT_EXT = 0x8FBB;

WebGLTimerQueryEXT? createQueryEXT();
WebGLTimerQueryEXT createQueryEXT();
undefined deleteQueryEXT(WebGLTimerQueryEXT? query);
[WebGLHandlesContextLoss] boolean isQueryEXT(WebGLTimerQueryEXT? query);
undefined beginQueryEXT(GLenum target, WebGLTimerQueryEXT query);
Expand Down Expand Up @@ -421,5 +421,8 @@ interface EXT_disjoint_timer_query {
<revision date="2023/06/01">
<change>Added error codes for invalid API usage.</change>
</revision>
<revision date="2024/04/19">
<change><code>createQueryEXT</code> made infallible.</change>
</revision>
</history>
</extension>
5 changes: 4 additions & 1 deletion extensions/OES_vertex_array_object/extension.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ interface WebGLVertexArrayObjectOES : WebGLObject {
interface OES_vertex_array_object {
const GLenum VERTEX_ARRAY_BINDING_OES = 0x85B5;

WebGLVertexArrayObjectOES? createVertexArrayOES();
WebGLVertexArrayObjectOES createVertexArrayOES();
undefined deleteVertexArrayOES(WebGLVertexArrayObjectOES? arrayObject);
[WebGLHandlesContextLoss] GLboolean isVertexArrayOES(WebGLVertexArrayObjectOES? arrayObject);
undefined bindVertexArrayOES(WebGLVertexArrayObjectOES? arrayObject);
Expand Down Expand Up @@ -167,5 +167,8 @@ interface OES_vertex_array_object {
<revision date="2022/07/09">
<change>Added error codes for invalid API usage.</change>
</revision>
<revision date="2024/04/19">
<change><code>createVertexArrayOES</code> made infallible.</change>
</revision>
</history>
</ratified>
6 changes: 3 additions & 3 deletions sdk/tests/conformance/context/context-lost-restored.html
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,13 @@
function testOESVertexArrayObject() {
if (OES_vertex_array_object) {
// Extension must still be lost.
shouldBeNull("OES_vertex_array_object.createVertexArrayOES()");
shouldBeNonNull("OES_vertex_array_object.createVertexArrayOES()");
kdashg marked this conversation as resolved.
Show resolved Hide resolved
// Try re-enabling extension

old_OES_vertex_array_object = OES_vertex_array_object;
OES_vertex_array_object = reGetExtensionAndTestForProperty(gl, "OES_vertex_array_object", false);
shouldBeTrue("OES_vertex_array_object.createVertexArrayOES() != null");
shouldBeTrue("old_OES_vertex_array_object.createVertexArrayOES() == null");
shouldBeNonNull("OES_vertex_array_object.createVertexArrayOES()");
shouldBeNonNull("old_OES_vertex_array_object.createVertexArrayOES()");
kdashg marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down
27 changes: 17 additions & 10 deletions sdk/tests/conformance/context/context-lost.html
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,6 @@

// Functions return nullable values should all return null.
var nullTests = [
"gl.createBuffer()",
"gl.createFramebuffer()",
"gl.createProgram()",
"gl.createRenderbuffer()",
"gl.createShader(gl.GL_VERTEX_SHADER)",
"gl.createTexture()",
"gl.getActiveAttrib(program, 0)",
"gl.getActiveUniform(program, 0)",
"gl.getAttachedShaders(program)",
Expand All @@ -336,6 +330,17 @@
];
testFunctionsThatReturnNULL(nullTests);

[
"gl.createBuffer()",
"gl.createFramebuffer()",
"gl.createProgram()",
"gl.createRenderbuffer()",
"gl.createShader(gl.VERTEX_SHADER)",
"gl.createTexture()",
].forEach(x => {
shouldBeNonNull(x);
kdashg marked this conversation as resolved.
Show resolved Hide resolved
});

// "Is" queries should all return false.
shouldBeFalse("gl.isBuffer(buffer)");
shouldBeFalse("gl.isEnabled(gl.BLEND)");
Expand All @@ -355,10 +360,12 @@
"OES_vertex_array_object.isVertexArrayOES(vertexArrayObject)",
"OES_vertex_array_object.deleteVertexArrayOES(vertexArrayObject)",
]);
testFunctionsThatReturnNULL(
[
"OES_vertex_array_object.createVertexArrayOES()",
]);

[
"OES_vertex_array_object.createVertexArrayOES()",
].forEach(x => {
shouldBeNonNull(x);
kdashg marked this conversation as resolved.
Show resolved Hide resolved
});
}

testUploadingLostContextToTexture();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@
finishTest();
return;
}
testLosingAndRestoringContext().then(function() {
testLosingAndRestoringContext().then(function(s) {
testPassed("Test passed");
finishTest();
return;
}, function() {
testFailed("Some test failed");
}, function(s) {
testFailed("Test failed: " + s);
finishTest();
return;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@
var worker = new Worker('context-lost-worker.js');
worker.postMessage("Start worker");
worker.onmessage = function(e) {
if (e.data == "Test passed") {
testPassed("All tests have passed");
} else {
testFailed("Some tests failed");
const fn = e.data.OffscreenCanvas ? testFailed : testPassed;
kdashg marked this conversation as resolved.
Show resolved Hide resolved
fn(e.data.msg);
if (e.data.finishTest) {
finishTest();
}
finishTest();
return;
}
}
Expand Down
18 changes: 8 additions & 10 deletions sdk/tests/conformance/offscreencanvas/context-lost-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,23 @@ self.onmessage = function(e) {

// call testValidContext() before checking for the extension, because this is where we check
// for the isContextLost() method, which we want to do regardless of the extension's presence.
if (!testValidContext())
self.postMessage("Test failed");
self.postMessage({fail: !testValidContext(), msg: "testValidContext()"});

WEBGL_lose_context = gl.getExtension("WEBGL_lose_context");
self.postMessage({fail: !WEBGL_lose_context, msg: "WEBGL_lose_context"});

extension = gl.getExtension("WEBGL_lose_context");
// need an extension that exposes new API methods.
OES_vertex_array_object = gl.getExtension("OES_vertex_array_object");
if (extension == null || OES_vertex_array_object == null)
self.postMessage("Test failed");
self.postMessage({fail: !OES_vertex_array_object, msg: "OES_vertex_array_object"});

// We need to initialize |uniformLocation| before losing context.
// Otherwise gl.getUniform() when context is lost will throw.
uniformLocation = gl.getUniformLocation(program, "tex");
extension.loseContext();
WEBGL_lose_context.loseContext();

canvas.addEventListener("webglcontextlost", function() {
if (testLostContextWithoutRestore())
self.postMessage("Test passed");
else
self.postMessage("Test failed");
self.postMessage({fail: !testLostContextWithoutRestore(), msg: "testLostContextWithoutRestore()",
finishTest:true});
}, false);
}

10 changes: 5 additions & 5 deletions sdk/tests/conformance/offscreencanvas/context-lost.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,27 @@
return;
}

extension = gl.getExtension("WEBGL_lose_context");
WEBGL_lose_context = gl.getExtension("WEBGL_lose_context");
// need an extension that exposes new API methods.
OES_vertex_array_object = gl.getExtension("OES_vertex_array_object");
if (extension == null || OES_vertex_array_object == null) {
testFailed("Some tests failed");
if (WEBGL_lose_context == null || OES_vertex_array_object == null) {
testFailed("extension && OES_vertex_array_object failed");
finishTest();
return;
}

// We need to initialize |uniformLocation| before losing context.
// Otherwise gl.getUniform() when context is lost will throw.
uniformLocation = gl.getUniformLocation(program, "tex");
extension.loseContext();
WEBGL_lose_context.loseContext();

canvas.addEventListener("webglcontextlost", function() {
if (testLostContextWithoutRestore()) {
testPassed("All tests passed");
finishTest();
return;
} else {
testFailed("Some tests failed");
testFailed("testLostContextWithoutRestore failed");
finishTest();
return;
}
Expand Down
44 changes: 30 additions & 14 deletions sdk/tests/js/tests/canvas-tests-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ var canvas;
var gl;
var OES_vertex_array_object;
var uniformLocation;
var extension;
var WEBGL_lose_context;
var buffer;
var framebuffer;
var program;
Expand Down Expand Up @@ -439,7 +439,7 @@ function testLostContextWithoutRestore()
return false;

// Test the extension itself.
if (!compareGLError(gl.INVALID_OPERATION, "extension.loseContext()"))
if (!compareGLError(gl.INVALID_OPERATION, "WEBGL_lose_context.loseContext()"))
return false;

imageData = new ImageData(1, 1);
Expand Down Expand Up @@ -567,13 +567,7 @@ function testLostContextWithoutRestore()
return false;

// Functions return nullable values should all return null.
if (gl.createBuffer() != null ||
gl.createFramebuffer() != null ||
gl.createProgram() != null ||
gl.createRenderbuffer() != null ||
gl.createShader(gl.GL_VERTEX_SHADER) != null ||
gl.createTexture() != null ||
gl.getActiveAttrib(program, 0) != null ||
if (gl.getActiveAttrib(program, 0) != null ||
gl.getActiveUniform(program, 0) != null ||
gl.getAttachedShaders(program) != null ||
gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE) != null ||
Expand All @@ -594,6 +588,22 @@ function testLostContextWithoutRestore()
gl.getExtension("WEBGL_lose_context") != null)
return false;

const failedTests = [
"gl.createBuffer()",
"gl.createFramebuffer()",
"gl.createProgram()",
"gl.createRenderbuffer()",
"gl.createShader(gl.VERTEX_SHADER)",
"gl.createTexture()",
].reduce(s => {
const v = eval(s);
return !v;
});
if (failedTests.length) {
console.log({failedTests});
return false;
}

// "Is" queries should all return false.
if (gl.isBuffer(buffer) || gl.isEnabled(gl.BLEND) || gl.isFramebuffer(framebuffer) ||
gl.isProgram(program) || gl.isRenderbuffer(renderbuffer) || gl.isShader(shader) ||
Expand All @@ -609,7 +619,7 @@ function testLostContextWithoutRestore()
!compareGLError(gl.NO_ERROR, "OES_vertex_array_object.isVertexArrayOES(vertexArrayObject)") ||
!compareGLError(gl.NO_ERROR, "OES_vertex_array_object.deleteVertexArrayOES(vertexArrayObject)"))
return false;
if (OES_vertex_array_object.createVertexArrayOES() != null)
if (!OES_vertex_array_object.createVertexArrayOES())
return false;
}
return true;
Expand Down Expand Up @@ -718,7 +728,7 @@ function testLosingAndRestoringContext()
});
canvas.addEventListener("webglcontextrestored", function() {
if (!testRestoredContext())
reject("Test failed");
reject("Test failed: !testRestoredContext()");
else
resolve("Test passed");
});
Expand Down Expand Up @@ -788,16 +798,22 @@ function testOESTextureFloat() {
function testOESVertexArrayObject() {
if (OES_vertex_array_object) {
// Extension must still be lost.
if (OES_vertex_array_object.createVertexArrayOES() != null)
if (!OES_vertex_array_object.createVertexArrayOES()) {
console.error("!OES_vertex_array_object.createVertexArrayOES()");
return false;
}
// Try re-enabling extension

var old_OES_vertex_array_object = OES_vertex_array_object;
OES_vertex_array_object = reGetExtensionAndTestForProperty(gl, "OES_vertex_array_object", false);
if (OES_vertex_array_object.createVertexArrayOES() == null)
if (!OES_vertex_array_object.createVertexArrayOES()) {
console.error("!OES_vertex_array_object.createVertexArrayOES() 2");
return false;
if (old_OES_vertex_array_object.createVertexArrayOES() != null)
}
if (!old_OES_vertex_array_object.createVertexArrayOES()) {
console.error("!old_OES_vertex_array_object.createVertexArrayOES()");
return false;
}
return true;
}
}
Expand Down
27 changes: 16 additions & 11 deletions specs/latest/1.0/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1815,12 +1815,12 @@ <h3><a name="WEBGLRENDERINGCONTEXT">The WebGL context</a></h3>
undefined copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLint x, GLint y, GLsizei width, GLsizei height);

WebGLBuffer? createBuffer();
WebGLFramebuffer? createFramebuffer();
WebGLProgram? createProgram();
WebGLRenderbuffer? createRenderbuffer();
WebGLBuffer createBuffer();
WebGLFramebuffer createFramebuffer();
WebGLProgram createProgram();
WebGLRenderbuffer createRenderbuffer();
WebGLShader? createShader(GLenum type);
WebGLTexture? createTexture();
WebGLTexture createTexture();

undefined cullFace(GLenum mode);

Expand Down Expand Up @@ -2399,7 +2399,7 @@ <h4>Buffer objects</h4>
an <code>INVALID_VALUE</code> error is generated. If <code>data</code> is null then
an <code>INVALID_VALUE</code> error is generated.

<dt class="idl-code">WebGLBuffer? createBuffer()
<dt class="idl-code">WebGLBuffer createBuffer()
<span class="gl-spec">(<a href="http://registry.khronos.org/OpenGL/specs/es/2.0/es_full_spec_2.0.pdf#nameddest=section-2.9">OpenGL ES 2.0 &sect;2.9</a>, similar to <a class="nonnormative" href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glGenBuffers.xml">glGenBuffers</a>)</span>
<dd>
Create a WebGLBuffer object and initialize it with a buffer object name as if by
Expand Down Expand Up @@ -2472,7 +2472,7 @@ <h4>Framebuffer objects</h4>
Returns <code class="enum">FRAMEBUFFER_UNSUPPORTED</code> if the
context's <a href="#webgl-context-lost-flag">webgl context lost flag</a> is set.

<dt class="idl-code">WebGLFramebuffer? createFramebuffer()
<dt class="idl-code">WebGLFramebuffer createFramebuffer()
<span class="gl-spec">(<a href="http://registry.khronos.org/OpenGL/specs/es/2.0/es_full_spec_2.0.pdf#nameddest=section-4.4.1">OpenGL ES 2.0 &sect;4.4.1</a>, similar to <a class="nonnormative" href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glGenFramebuffers.xml">glGenFramebuffers</a>)</span>
<dd>
Create a WebGLFramebuffer object and initialize it with a framebuffer object name as if by
Expand Down Expand Up @@ -2554,7 +2554,7 @@ <h4>Renderbuffer objects</h4>
An attempt to bind an object marked for deletion will generate an
<code>INVALID_OPERATION</code> error, and the current binding will remain untouched.

<dt class="idl-code">WebGLRenderbuffer? createRenderbuffer()
<dt class="idl-code">WebGLRenderbuffer createRenderbuffer()
<span class="gl-spec">(<a href="http://registry.khronos.org/OpenGL/specs/es/2.0/es_full_spec_2.0.pdf#nameddest=section-4.4.3">OpenGL ES 2.0 &sect;4.4.3</a>, similar to <a class="nonnormative" href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glGenRenderbuffers.xml">glGenRenderbuffers</a>)</span>
<dd>
Create a WebGLRenderbuffer object and initialize it with a renderbuffer object name as if by
Expand Down Expand Up @@ -2679,7 +2679,7 @@ <h4>Texture objects</h4>
If this function attempts to read from a complete framebuffer with a missing attachment,
an <code>INVALID_OPERATION</code> error is generated
per <a href="#READING_FROM_MISSING_ATTACHMENT">Reading from a Missing Attachment</a>.
<dt class="idl-code">WebGLTexture? createTexture()
<dt class="idl-code">WebGLTexture createTexture()
<span class="gl-spec">(<a href="http://registry.khronos.org/OpenGL/specs/es/2.0/es_full_spec_2.0.pdf#nameddest=section-3.7.13">OpenGL ES 2.0 &sect;3.7.13</a>, <a class="nonnormative" href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glGenTextures.xml">man page</a>)</span>
<dd>
Create a WebGLTexture object and initialize it with a texture object name as if by
Expand Down Expand Up @@ -3001,7 +3001,7 @@ <h4>Programs and Shaders</h4>
Shaders</a>, and <a href="#PACKING_RESTRICTIONS">Packing Restrictions for Uniforms and
Varyings</a> for additional constraints enforced in, additional constructs supported by,
and additional validation performed by WebGL implementations.
<dt class="idl-code">WebGLProgram? createProgram()
<dt class="idl-code">WebGLProgram createProgram()
<span class="gl-spec">(<a href="http://registry.khronos.org/OpenGL/specs/es/2.0/es_full_spec_2.0.pdf#nameddest=section-2.10.3">OpenGL ES 2.0 &sect;2.10.3</a>, <a class="nonnormative" href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glCreateProgram.xml">man page</a>)</span>
<dd>
Create a WebGLProgram object and initialize it with a program object name as if by
Expand Down Expand Up @@ -3710,6 +3710,11 @@ <h4><a name="CONTEXT_LOST">The Context Lost Event</a></h4>
</li>
</ol>
</p>
<p>
A <code>WebGLObject</code> created while the context is lost
(e.g. a <code>WebGLBuffer</code> via <code>createBuffer()</code>)
begins life with its <a href="#webgl-object-invalidated-flag">invalidated flag</a> set.
</p>
<div class="example">
The following code prevents the default behavior of the <code>webglcontextlost</code>
event and enables the <code>webglcontextrestored</code> event to be delivered:
Expand Down Expand Up @@ -3751,7 +3756,7 @@ <h4><a name="CONTEXT_RESTORED">The Context Restored Event</a></h4>

<div class="note">
Once the context is restored, WebGL resources such as textures and buffers that were created
before the context was lost are no longer valid.
before the context was restored are no longer valid.
Previously enabled extensions are not restored.
The application will want to restore all modified state and destroyed extensions and resources.
</div>
Expand Down
Loading
Loading