<!--

/*
** 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="../../../js/js-test-pre.js"></script>
<script src="../../../js/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>
