diff --git a/extensions/EXT_disjoint_timer_query/extension.xml b/extensions/EXT_disjoint_timer_query/extension.xml index 3cbab755de..5739c8926b 100644 --- a/extensions/EXT_disjoint_timer_query/extension.xml +++ b/extensions/EXT_disjoint_timer_query/extension.xml @@ -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); @@ -421,5 +421,8 @@ interface EXT_disjoint_timer_query { Added error codes for invalid API usage. + + createQueryEXT made infallible. + diff --git a/extensions/OES_vertex_array_object/extension.xml b/extensions/OES_vertex_array_object/extension.xml index 224be15839..af688940d0 100644 --- a/extensions/OES_vertex_array_object/extension.xml +++ b/extensions/OES_vertex_array_object/extension.xml @@ -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); @@ -167,5 +167,8 @@ interface OES_vertex_array_object { Added error codes for invalid API usage. + + createVertexArrayOES made infallible. + diff --git a/sdk/tests/conformance/context/context-lost-restored.html b/sdk/tests/conformance/context/context-lost-restored.html index 6942e3d1ce..091543b0be 100644 --- a/sdk/tests/conformance/context/context-lost-restored.html +++ b/sdk/tests/conformance/context/context-lost-restored.html @@ -239,13 +239,24 @@ function testOESVertexArrayObject() { if (OES_vertex_array_object) { // Extension must still be lost. - shouldBeNull("OES_vertex_array_object.createVertexArrayOES()"); + let vao = OES_vertex_array_object.createVertexArrayOES(); + assertMsg(vao, "[with extension lost] createVertexArrayOES() -> non-null"); + assertMsg(!OES_vertex_array_object.isVertexArrayOES(vao), "[with context lost] isVertexArrayOES(createVertexArrayOES()) -> false"); // 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"); + + vao = OES_vertex_array_object.createVertexArrayOES(); + assertMsg(vao, "[with new non-lost extension] createVertexArrayOES() -> non-null"); + assertMsg(!OES_vertex_array_object.isVertexArrayOES(vao), "[with new non-lost extension, before bindVAO] isVertexArrayOES(createVertexArrayOES()) -> false"); + OES_vertex_array_object.bindVertexArrayOES(vao); + OES_vertex_array_object.bindVertexArrayOES(null); + assertMsg(OES_vertex_array_object.isVertexArrayOES(vao), "[with new non-lost extension, after bindVAO] isVertexArrayOES(createVertexArrayOES()) -> true"); + + vao = old_OES_vertex_array_object.createVertexArrayOES(); + assertMsg(vao, "[with old lost extension] createVertexArrayOES() -> non-null"); + assertMsg(!old_OES_vertex_array_object.isVertexArrayOES(vao), "[with old lost extension] isVertexArrayOES(createVertexArrayOES()) -> false"); } } diff --git a/sdk/tests/conformance/context/context-lost.html b/sdk/tests/conformance/context/context-lost.html index 31d07a94a9..e9ef6bdb25 100644 --- a/sdk/tests/conformance/context/context-lost.html +++ b/sdk/tests/conformance/context/context-lost.html @@ -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)", @@ -336,14 +330,24 @@ ]; testFunctionsThatReturnNULL(nullTests); + [ + [() => gl.createBuffer(), x => gl.bindBuffer(gl.ARRAY_BUFFER, x), x => gl.isBuffer(x)], + [() => gl.createFramebuffer(), x => gl.bindFramebuffer(gl.FRAMEBUFFER, x), x => gl.isFramebuffer(x)], + [() => gl.createProgram(), x => undefined, x => gl.isProgram(x)], + [() => gl.createRenderbuffer(), x => gl.bindRenderbuffer(gl.RENDERBUFFER, x), x => gl.isRenderbuffer(x)], + [() => gl.createShader(gl.VERTEX_SHADER), x => undefined, x => gl.isShader(x)], + [() => gl.createTexture(), x => gl.bindTexture(gl.TEXTURE_2D, x), x => gl.isTexture(x)], + ].forEach(([fn_create, fn_bind, fn_is]) => { + const x = fn_create(); + assertMsg(x, `${fn_create.toString()} -> non-null`); + assertMsg(fn_is(x) === false, `[before bind] ${fn_is.toString()} -> false`); + fn_bind(x); + fn_bind(null); + assertMsg(fn_is(x) === false, `[after bind] ${fn_is.toString()} -> false`); + }); + // "Is" queries should all return false. - shouldBeFalse("gl.isBuffer(buffer)"); shouldBeFalse("gl.isEnabled(gl.BLEND)"); - shouldBeFalse("gl.isFramebuffer(framebuffer)"); - shouldBeFalse("gl.isProgram(program)"); - shouldBeFalse("gl.isRenderbuffer(renderbuffer)"); - shouldBeFalse("gl.isShader(shader)"); - shouldBeFalse("gl.isTexture(texture)"); shouldBe("gl.getError()", "gl.NO_ERROR"); @@ -355,10 +359,17 @@ "OES_vertex_array_object.isVertexArrayOES(vertexArrayObject)", "OES_vertex_array_object.deleteVertexArrayOES(vertexArrayObject)", ]); - testFunctionsThatReturnNULL( - [ - "OES_vertex_array_object.createVertexArrayOES()", - ]); + + [ + [() => OES_vertex_array_object.createVertexArrayOES(), x => OES_vertex_array_object.isVertexArrayOES(x), x => OES_vertex_array_object.isVertexArrayOES(x)], + ].forEach(([fn_create, fn_bind, fn_is]) => { + const x = fn_create(); + assertMsg(x, `${fn_create.toString()} -> non-null`); + assertMsg(fn_is(x) === false, `[before bind] ${fn_is.toString()} -> false`); + fn_bind(x); + fn_bind(null); + assertMsg(fn_is(x) === false, `[after bind] ${fn_is.toString()} -> false`); + }); } testUploadingLostContextToTexture(); diff --git a/sdk/tests/conformance/offscreencanvas/context-lost-restored.html b/sdk/tests/conformance/offscreencanvas/context-lost-restored.html index 28e1878179..2028117462 100644 --- a/sdk/tests/conformance/offscreencanvas/context-lost-restored.html +++ b/sdk/tests/conformance/offscreencanvas/context-lost-restored.html @@ -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; }); diff --git a/sdk/tests/conformance/offscreencanvas/context-lost-worker.html b/sdk/tests/conformance/offscreencanvas/context-lost-worker.html index a4846712de..74a8eb9be0 100644 --- a/sdk/tests/conformance/offscreencanvas/context-lost-worker.html +++ b/sdk/tests/conformance/offscreencanvas/context-lost-worker.html @@ -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.fail ? testFailed : testPassed; + fn(e.data.msg); + if (e.data.finishTest) { + finishTest(); } - finishTest(); return; } } diff --git a/sdk/tests/conformance/offscreencanvas/context-lost-worker.js b/sdk/tests/conformance/offscreencanvas/context-lost-worker.js index 75cd4b0045..ee5e2f32ec 100644 --- a/sdk/tests/conformance/offscreencanvas/context-lost-worker.js +++ b/sdk/tests/conformance/offscreencanvas/context-lost-worker.js @@ -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); } diff --git a/sdk/tests/conformance/offscreencanvas/context-lost.html b/sdk/tests/conformance/offscreencanvas/context-lost.html index 0568ad229e..711af21682 100644 --- a/sdk/tests/conformance/offscreencanvas/context-lost.html +++ b/sdk/tests/conformance/offscreencanvas/context-lost.html @@ -33,11 +33,11 @@ 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; } @@ -45,7 +45,7 @@ // 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()) { @@ -53,7 +53,7 @@ finishTest(); return; } else { - testFailed("Some tests failed"); + testFailed("testLostContextWithoutRestore failed"); finishTest(); return; } diff --git a/sdk/tests/js/tests/canvas-tests-utils.js b/sdk/tests/js/tests/canvas-tests-utils.js index 1921a25df8..90f34f0745 100644 --- a/sdk/tests/js/tests/canvas-tests-utils.js +++ b/sdk/tests/js/tests/canvas-tests-utils.js @@ -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; @@ -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); @@ -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 || @@ -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) || @@ -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; @@ -718,7 +728,7 @@ function testLosingAndRestoringContext() }); canvas.addEventListener("webglcontextrestored", function() { if (!testRestoredContext()) - reject("Test failed"); + reject("Test failed: !testRestoredContext()"); else resolve("Test passed"); }); @@ -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; } } diff --git a/specs/latest/1.0/index.html b/specs/latest/1.0/index.html index 074903f43b..c862504549 100644 --- a/specs/latest/1.0/index.html +++ b/specs/latest/1.0/index.html @@ -1823,12 +1823,12 @@

The WebGL context

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); @@ -2407,7 +2407,7 @@

Buffer objects

an INVALID_VALUE error is generated. If data is null then an INVALID_VALUE error is generated. -
WebGLBuffer? createBuffer() +
WebGLBuffer createBuffer() (OpenGL ES 2.0 §2.9, similar to glGenBuffers)
Create a WebGLBuffer object and initialize it with a buffer object name as if by @@ -2480,7 +2480,7 @@

Framebuffer objects

Returns FRAMEBUFFER_UNSUPPORTED if the context's webgl context lost flag is set. -
WebGLFramebuffer? createFramebuffer() +
WebGLFramebuffer createFramebuffer() (OpenGL ES 2.0 §4.4.1, similar to glGenFramebuffers)
Create a WebGLFramebuffer object and initialize it with a framebuffer object name as if by @@ -2562,7 +2562,7 @@

Renderbuffer objects

An attempt to bind an object marked for deletion will generate an INVALID_OPERATION error, and the current binding will remain untouched. -
WebGLRenderbuffer? createRenderbuffer() +
WebGLRenderbuffer createRenderbuffer() (OpenGL ES 2.0 §4.4.3, similar to glGenRenderbuffers)
Create a WebGLRenderbuffer object and initialize it with a renderbuffer object name as if by @@ -2687,7 +2687,7 @@

Texture objects

If this function attempts to read from a complete framebuffer with a missing attachment, an INVALID_OPERATION error is generated per Reading from a Missing Attachment. -
WebGLTexture? createTexture() +
WebGLTexture createTexture() (OpenGL ES 2.0 §3.7.13, man page)
Create a WebGLTexture object and initialize it with a texture object name as if by @@ -3009,7 +3009,7 @@

Programs and Shaders

Shaders, and Packing Restrictions for Uniforms and Varyings for additional constraints enforced in, additional constructs supported by, and additional validation performed by WebGL implementations. -
WebGLProgram? createProgram() +
WebGLProgram createProgram() (OpenGL ES 2.0 §2.10.3, man page)
Create a WebGLProgram object and initialize it with a program object name as if by @@ -3718,6 +3718,11 @@

The Context Lost Event

+

+ A WebGLObject created while the context is lost + (e.g. a WebGLBuffer via createBuffer()) + begins life with its invalidated flag set. +

The following code prevents the default behavior of the webglcontextlost event and enables the webglcontextrestored event to be delivered: @@ -3759,7 +3764,7 @@

The Context Restored Event

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.
diff --git a/specs/latest/2.0/index.html b/specs/latest/2.0/index.html index 55120f0360..27fb563c6f 100644 --- a/specs/latest/2.0/index.html +++ b/specs/latest/2.0/index.html @@ -826,7 +826,7 @@

The WebGL context

undefined clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); /* Query Objects */ - WebGLQuery? createQuery(); + WebGLQuery createQuery(); undefined deleteQuery(WebGLQuery? query); [WebGLHandlesContextLoss] GLboolean isQuery(WebGLQuery? query); undefined beginQuery(GLenum target, WebGLQuery query); @@ -835,7 +835,7 @@

The WebGL context

any getQueryParameter(WebGLQuery query, GLenum pname); /* Sampler Objects */ - WebGLSampler? createSampler(); + WebGLSampler createSampler(); undefined deleteSampler(WebGLSampler? sampler); [WebGLHandlesContextLoss] GLboolean isSampler(WebGLSampler? sampler); undefined bindSampler(GLuint unit, WebGLSampler? sampler); @@ -852,7 +852,7 @@

The WebGL context

any getSyncParameter(WebGLSync sync, GLenum pname); /* Transform Feedback */ - WebGLTransformFeedback? createTransformFeedback(); + WebGLTransformFeedback createTransformFeedback(); undefined deleteTransformFeedback(WebGLTransformFeedback? tf); [WebGLHandlesContextLoss] GLboolean isTransformFeedback(WebGLTransformFeedback? tf); undefined bindTransformFeedback (GLenum target, WebGLTransformFeedback? tf); @@ -875,7 +875,7 @@

The WebGL context

undefined uniformBlockBinding(WebGLProgram program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); /* Vertex Array Objects */ - WebGLVertexArrayObject? createVertexArray(); + WebGLVertexArrayObject createVertexArray(); undefined deleteVertexArray(WebGLVertexArrayObject? vertexArray); [WebGLHandlesContextLoss] GLboolean isVertexArray(WebGLVertexArrayObject? vertexArray); undefined bindVertexArray(WebGLVertexArrayObject? array);