diff options
Diffstat (limited to '')
-rw-r--r-- | dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost-restored.html | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost-restored.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost-restored.html new file mode 100644 index 0000000000..6942e3d1ce --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost-restored.html @@ -0,0 +1,287 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +<script> +"use strict"; +var wtu = WebGLTestUtils; +var canvas; +var gl; +var shouldGenerateGLError; +var WEBGL_lose_context; +var new_WEBGL_lose_context; +var bufferObjects; +var program; +var texture; +var texColor = [255, 10, 20, 255]; +var allowRestore; +var contextLostEventFired; +var contextRestoredEventFired; +var OES_vertex_array_object; +var old_OES_vertex_array_object; +var vertexArrayObject; +var OES_texture_float; +var newExtension; + +function init() +{ + enableJSTestPreVerboseLogging(); + description("Tests behavior under a restored context."); + + shouldGenerateGLError = wtu.shouldGenerateGLError; + testLosingContext(); +} + +function setupTest() +{ + canvas = document.createElement("canvas"); + canvas.width = 1; + canvas.height = 1; + gl = wtu.create3DContext(canvas); + WEBGL_lose_context = getExtensionAndAddProperty(gl, "WEBGL_lose_context"); + if (!WEBGL_lose_context) { + debug("Could not find WEBGL_lose_context extension"); + 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. + shouldBeTrue("newExtension != null"); + if (expectProperty) { + shouldBeTrue("newExtension.webglTestProperty === true"); + } else { + shouldBeTrue("newExtension.webglTestProperty === undefined"); + } + return newExtension; +} + +function testLosingContext() +{ + if (!setupTest()) { + finishTest(); + return; + } + + debug("Test losing a context and inability to restore it."); + + canvas.addEventListener("webglcontextlost", 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 + shouldGenerateGLError(gl, gl.INVALID_OPERATION, "WEBGL_lose_context.restoreContext()"); + testLosingAndRestoringContext(); + }, 0); + }); + canvas.addEventListener("webglcontextrestored", testShouldNotRestoreContext); + allowRestore = false; + contextLostEventFired = false; + contextRestoredEventFired = false; + + testOriginalContext(); + WEBGL_lose_context.loseContext(); + // The context should be lost immediately. + shouldBeTrue("gl.isContextLost()"); + shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL"); + shouldBe("gl.getError()", "gl.NO_ERROR"); + // gl methods should be no-ops + shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)"); + // but the event should not have been fired. + shouldBeFalse("contextLostEventFired"); +} + +function testLosingAndRestoringContext() +{ + if (!setupTest()) + finishTest(); + + debug(""); + debug("Test losing and restoring a context."); + + canvas.addEventListener("webglcontextlost", function(e) { + testLostContext(e); + // restore the context after this event has exited. + setTimeout(function() { + shouldGenerateGLError(gl, gl.NO_ERROR, "WEBGL_lose_context.restoreContext()"); + // Calling restoreContext() twice should not cause error or crash + shouldGenerateGLError(gl, gl.NO_ERROR, "WEBGL_lose_context.restoreContext()"); + // The context should still be lost. It will not get restored until the + // webglrestorecontext event is fired. + shouldBeTrue("gl.isContextLost()"); + shouldBe("gl.getError()", "gl.NO_ERROR"); + // gl methods should still be no-ops + shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)"); + }, 0); + }); + canvas.addEventListener("webglcontextrestored", function() { + testRestoredContext(); + finishTest(); + }); + allowRestore = true; + contextLostEventFired = false; + contextRestoredEventFired = false; + + testOriginalContext(); + WEBGL_lose_context.loseContext(); + // The context should be lost immediately. + shouldBeTrue("gl.isContextLost()"); + shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL"); + shouldBe("gl.getError()", "gl.NO_ERROR"); + // gl methods should be no-ops + shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)"); + // but the event should not have been fired. + shouldBeFalse("contextLostEventFired"); +} + +function testRendering() +{ + gl.clearColor(0, 0, 0, 255); + gl.colorMask(1, 1, 1, 0); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + + program = wtu.setupSimpleTextureProgram(gl); + bufferObjects = wtu.setupUnitQuad(gl); + texture = wtu.createColoredTexture(gl, canvas.width, canvas.height, texColor); + + gl.uniform1i(gl.getUniformLocation(program, "tex"), 0); + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + + var compare = texColor.slice(0, 3); + wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, compare, "shouldBe " + compare); + + shouldBe("gl.getError()", "gl.NO_ERROR"); +} + +function testOriginalContext() +{ + debug("Test valid context"); + shouldBeFalse("gl.isContextLost()"); + shouldBe("gl.getError()", "gl.NO_ERROR"); + testRendering(); + debug(""); +} + +function testLostContext(e) +{ + debug("Test lost context"); + shouldBeFalse("contextLostEventFired"); + contextLostEventFired = true; + shouldBeTrue("gl.isContextLost()"); + shouldBe("gl.getError()", "gl.NO_ERROR"); + debug(""); + if (allowRestore) + e.preventDefault(); +} + +function testShouldNotRestoreContext(e) +{ + testFailed("Should not restore the context unless preventDefault is called on the context lost event"); + debug(""); +} + +function testResources(expected) +{ + var tests = [ + "gl.bindTexture(gl.TEXTURE_2D, texture)", + "gl.useProgram(program)", + "gl.bindBuffer(gl.ARRAY_BUFFER, bufferObjects[0])", + ]; + + for (var i = 0; i < tests.length; ++i) + shouldGenerateGLError(gl, expected, tests[i]); +} + +function testOESTextureFloat() { + if (OES_texture_float) { + // Extension must still be lost. + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + shouldGenerateGLError(gl, 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); + shouldGenerateGLError(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. + shouldBeNull("OES_vertex_array_object.createVertexArrayOES()"); + // 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"); + } +} + +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() +{ + debug("Test restored context"); + shouldBeFalse("contextRestoredEventFired"); + contextRestoredEventFired = true; + shouldBeFalse("gl.isContextLost()"); + shouldBe("gl.getError()", "gl.NO_ERROR"); + + // Validate that using old resources fails. + testResources(gl.INVALID_OPERATION); + + testRendering(); + + // Validate new resources created in testRendering(). + testResources(gl.NO_ERROR); + + testExtensions(); + + debug(""); +} + + +</script> +</head> +<body onload="init()"> +<div id="description"></div> +<div id="console"></div> +</body> +</html> |