| <!DOCTYPE html> |
| <html> |
| <head> |
| <script src="../../../resources/testharness.js"></script> |
| <script src="../../../resources/testharnessreport.js"></script> |
| <script src="./resources/webgl-test.js"></script> |
| <script src="./resources/webgl-test-utils-full.js"></script> |
| </head> |
| <body> |
| <script> |
| var wtu = WebGLTestUtils; |
| var canvas; |
| var gl; |
| var WEBGL_lose_context; |
| var new_WEBGL_lose_context; |
| var allowRestore; |
| var contextLostEventFired; |
| var contextRestoredEventFired; |
| var OES_vertex_array_object; |
| var old_OES_vertex_array_object; |
| var OES_texture_float; |
| var newExtension; |
| |
| async_test(function(t) { |
| if (!setupTest()) { |
| assert_true(false, 'Cannot initialize test'); |
| t.done(); |
| } |
| |
| canvas.addEventListener("webglcontextlost", t.step_func(function(e) { |
| testLostContext(e); |
| // restore the context after this event has exited. |
| setTimeout(function() { |
| // we didn't call prevent default so we should not be able to restore the context |
| compareGLError(gl.INVALID_OPERATION, "WEBGL_lose_context.restoreContext()"); |
| testLosingAndRestoringContext(t); |
| }, 0); |
| })); |
| canvas.addEventListener("webglcontextrestored", testShouldNotRestoreContext); |
| allowRestore = false; |
| contextLostEventFired = false; |
| contextRestoredEventFired = false; |
| |
| testOriginalContext(); |
| WEBGL_lose_context.loseContext(); |
| // The context should be lost immediately. |
| assert_true(gl.isContextLost()); |
| assert_equals(gl.getError(), gl.CONTEXT_LOST_WEBGL); |
| assert_equals(gl.getError(), gl.NO_ERROR); |
| // gl methods should be no-ops |
| compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)"); |
| // but the event should not have been fired. |
| assert_false(contextLostEventFired); |
| }, 'Test WebGL context restoration with OffscreenCanvas'); |
| |
| function compareGLError(glError, evalStr) |
| { |
| var exception; |
| try { |
| eval(evalStr); |
| } catch (e) { |
| exception = e; |
| } |
| if (exception) { |
| assert_true(false, evalStr + " threw exception " + exception); |
| } else { |
| assert_equals(gl.getError(), glError); |
| } |
| } |
| |
| function setupTest() |
| { |
| canvas = new OffscreenCanvas(10, 10); |
| gl = canvas.getContext('webgl'); |
| WEBGL_lose_context = getExtensionAndAddProperty(gl, "WEBGL_lose_context"); |
| if (!WEBGL_lose_context) |
| return false; |
| |
| // Try to get a few extensions |
| OES_vertex_array_object = getExtensionAndAddProperty(gl, "OES_vertex_array_object"); |
| OES_texture_float = getExtensionAndAddProperty(gl, "OES_texture_float"); |
| |
| return true; |
| } |
| |
| function getExtensionAndAddProperty(gl, name) { |
| var ext = wtu.getExtensionWithKnownPrefixes(gl, name); |
| if (ext) { |
| ext.webglTestProperty = true; |
| } |
| return ext; |
| } |
| |
| function reGetExtensionAndTestForProperty(gl, name, expectProperty) { |
| newExtension = wtu.getExtensionWithKnownPrefixes(gl, name); |
| // NOTE: while getting a extension after context lost/restored is allowed to fail |
| // for the purpose the conformance tests it is not. |
| // |
| // Hypothetically the user can switch GPUs live. For example on Windows, install 2 GPUs, |
| // then in the control panen enable 1, disable the others and visa versa. Since the GPUs |
| // have different capabilities one or the other may not support a particlar extension. |
| // |
| // But, for the purpose of the conformance tests the context is expected to restore |
| // on the same GPU and therefore the extensions that succeeded previously should |
| // succeed on restore. |
| assert_true(newExtension != null); |
| if (expectProperty) { |
| assert_true(newExtension.webglTestProperty === true); |
| } else { |
| assert_true(newExtension.webglTestProperty === undefined); |
| } |
| return newExtension; |
| } |
| |
| function testLosingAndRestoringContext(t) |
| { |
| if (!setupTest()) { |
| assert_true(false, 'Cannot initialize test'); |
| t.done(); |
| } |
| |
| canvas.addEventListener("webglcontextlost", function(e) { |
| testLostContext(e); |
| // restore the context after this event has exited. |
| setTimeout(function() { |
| compareGLError(gl.NO_ERROR, "WEBGL_lose_context.restoreContext()"); |
| // The context should still be lost. It will not get restored until the |
| // webglrestorecontext event is fired. |
| assert_true(gl.isContextLost()); |
| assert_equals(gl.getError(), gl.NO_ERROR); |
| // gl methods should still be no-ops |
| compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)"); |
| }, 0); |
| }); |
| canvas.addEventListener("webglcontextrestored", t.step_func_done(function() { |
| testRestoredContext(); |
| })); |
| allowRestore = true; |
| contextLostEventFired = false; |
| contextRestoredEventFired = false; |
| |
| testOriginalContext(); |
| WEBGL_lose_context.loseContext(); |
| // The context should be lost immediately. |
| assert_true(gl.isContextLost()); |
| assert_equals(gl.getError(), gl.CONTEXT_LOST_WEBGL); |
| assert_equals(gl.getError(), gl.NO_ERROR); |
| // gl methods should be no-ops |
| compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)"); |
| // but the event should not have been fired. |
| assert_false(contextLostEventFired); |
| } |
| |
| function testOriginalContext() |
| { |
| assert_false(gl.isContextLost()); |
| assert_equals(gl.getError(), gl.NO_ERROR); |
| } |
| |
| function testLostContext(e) |
| { |
| assert_false(contextLostEventFired); |
| contextLostEventFired = true; |
| assert_true(gl.isContextLost()); |
| assert_equals(gl.getError(), gl.NO_ERROR); |
| if (allowRestore) |
| e.preventDefault(); |
| } |
| |
| function testShouldNotRestoreContext(e) |
| { |
| assert_true(false, "Should not restore the context unless preventDefault is called on the context lost event"); |
| } |
| |
| function testOESTextureFloat() { |
| if (OES_texture_float) { |
| // Extension must still be lost. |
| var tex = gl.createTexture(); |
| gl.bindTexture(gl.TEXTURE_2D, tex); |
| compareGLError(gl.INVALID_ENUM, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null)"); |
| // Try re-enabling extension |
| OES_texture_float = reGetExtensionAndTestForProperty(gl, "OES_texture_float", false); |
| compareGLError(gl, gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null)"); |
| } |
| } |
| |
| function testOESVertexArrayObject() { |
| if (OES_vertex_array_object) { |
| // Extension must still be lost. |
| assert_equals(OES_vertex_array_object.createVertexArrayOES(), null); |
| // Try re-enabling extension |
| |
| old_OES_vertex_array_object = OES_vertex_array_object; |
| OES_vertex_array_object = reGetExtensionAndTestForProperty(gl, "OES_vertex_array_object", false); |
| assert_true(OES_vertex_array_object.createVertexArrayOES() != null); |
| assert_true(old_OES_vertex_array_object.createVertexArrayOES() == null); |
| } |
| } |
| |
| function testExtensions() { |
| testOESTextureFloat(); |
| testOESVertexArrayObject(); |
| // Only the WEBGL_lose_context extension should be the same object after context lost. |
| new_WEBGL_lose_context = reGetExtensionAndTestForProperty(gl, "WEBGL_lose_context", true); |
| } |
| |
| function testRestoredContext() |
| { |
| assert_false(contextRestoredEventFired); |
| contextRestoredEventFired = true; |
| assert_false(gl.isContextLost()); |
| assert_equals(gl.getError(), gl.NO_ERROR); |
| testExtensions(); |
| } |
| </script> |
| </body> |
| </html> |