<!--

/*
** Copyright (c) 2012 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/

-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../resources/js-test-pre.js"></script>
<script src="../resources/webgl-test-utils.js"></script>
<script>
"use strict";
var wtu = WebGLTestUtils;
var gl = null;
var textureLoc = null;
var successfullyParsed = false;

initTestingHarness();

function init()
{
    description('Verify npot video');

    var canvas = document.getElementById("example");
    gl = wtu.create3DContext(canvas);
    var program = wtu.setupTexturedQuad(gl);

    gl.clearColor(0,0,0,1);
    gl.clearDepth(1);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    // Disable any writes to the alpha channel
    gl.colorMask(1, 1, 1, 0);

    textureLoc = gl.getUniformLocation(program, "tex");

    var video = document.getElementById("vid");
    wtu.startPlayingAndWaitForVideo(video, runTest);
}

function runOneIteration(videoElement, useTexSubImage2D, flipY, topColor, bottomColor, badMinFilter, badClamp, genMips)
{
    debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') +
          ' with flipY=' + flipY);
    var texture = gl.createTexture();
    // Bind the texture to texture unit 0
    gl.bindTexture(gl.TEXTURE_2D, texture);
    // Set up pixel store parameters
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
    // Upload the videoElement into the texture
    debug("size: " + videoElement.videoWidth + "x" + videoElement.videoHeight);
    if (useTexSubImage2D) {
        // Initialize the texture to black first
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA,
                      videoElement.videoWidth, videoElement.videoHeight, 0,
                      gl.RGBA, gl.UNSIGNED_BYTE, null);
        gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, videoElement);
    } else {
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, videoElement);
    }

    // Set up texture parameters
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    if (badMinFilter) {
        debug("bad min filter");
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
    } else {
        debug("good min filter");
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    }
    if (badClamp) {
        debug("bad clamp");
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
    } else {
        debug("good clamp");
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    }
    if (genMips) {
        debug("generate mips");
        gl.generateMipmap(gl.TEXTURE_2D);
        wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should be INVALID_OPERATION");
    }

//    var c = document.createElement("canvas");
//    c.width = 16;
//    c.height = 16;
//    c.style.border = "1px solid black";
//    var ctx = c.getContext("2d");
//    ctx.drawImage(videoElement, 0, 0, 16, 16);
//    document.body.appendChild(c);

    // Point the uniform sampler to texture unit 0
    gl.uniform1i(textureLoc, 0);
    // Draw the triangles
    wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
    // Check a few pixels near the top and bottom and make sure they have
    // the right color.
    var tolerance = 5;
    debug("Checking lower left corner");
    wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor,
                        "shouldBe " + bottomColor, tolerance);
    debug("Checking upper left corner");
    wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor,
                        "shouldBe " + topColor, tolerance);
    debug("");
}

function runTest(videoElement)
{
    var red = [255, 0, 0];
    var green = [0, 255, 0];
    var black = [0, 0, 0];
    runOneIteration(videoElement, false, true, black, black, true, true, true);
    runOneIteration(videoElement, false, true, black, black, true, false, false);
    runOneIteration(videoElement, false, true, black, black, false, true, false);
    runOneIteration(videoElement, false, true, black, black, true, true, false);
    runOneIteration(videoElement, false, true, green, red, false, false, false);
    runOneIteration(videoElement, false, false, red, green, false, false, false);
    runOneIteration(videoElement, true, true, green, red, false, false, false);
    runOneIteration(videoElement, true, false, red, green, false, false, false);

    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
    finishTest();
}
</script>
</head>
<body onload="init()">
<canvas id="example" width="64" height="48"></canvas>
<div id="description"></div>
<div id="console"></div>
<video id="vid" style="display:none;">
  <source src="../resources/npot-video.mp4"  type='video/mp4; codecs="avc1.42E01E"' />
  <source src="../resources/npot-video.webmvp8.webm" type='video/webm; codecs="vp8"' />
  <source src="../resources/npot-video.theora.ogv"  type='video/ogg; codecs="theora"' />
</video>
</body>
</html>
