<!DOCTYPE html>
<html>
<head>
<script src="../../../resources/js-test.js"></script>
<script src="resources/webgl-test.js"></script>
<script src="resources/webgl-test-utils.js"></script>
<script>
if (window.internals)
    window.internals.settings.setWebGLErrorsToConsoleEnabled(false);

var wtu = WebGLTestUtils;
var canvas;
var gl;
var shouldGenerateGLError;
var extension;
var bufferObjects;
var program;
var texture;
var texColor = [255, 10, 20, 255];
var allowRestore;
var contextLostEventFired;
var contextRestoredEventFired;

function init()
{
    if (window.initNonKhronosFramework) {
        window.initNonKhronosFramework(true);
    }

    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);
    extension = gl.getExtension("WEBGL_lose_context");
    if (!extension) {
        debug("Could not find lose_context extension under the following names: WEBGL_lose_context");
        return false;
    }
    return true;
}

function testLosingContext()
{
    if (!setupTest())
        finishTest();

    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, "extension.restoreContext()");
         testLosingAndRestoringContext();
       }, 0);
    });
    canvas.addEventListener("webglcontextrestored", testShouldNotRestoreContext);
    allowRestore = false;
    contextLostEventFired = false;
    contextRestoredEventFired = false;

    testOriginalContext();
    extension.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, "extension.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();
    extension.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.drawQuad(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 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);
    debug("");
}


</script>
</head>
<body onload="init()">
<div id="description"></div>
<div id="console"></div>
</body>
</html>
