<!--
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.
-->
<!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 expectedVideoHeightLoc = null;
var successfullyParsed = false;
var resourcePath = "../../../resources/";
// Test each format separately because many browsers implement each
// differently. Some might be GPU accelerated, some might not. Etc...
var videos = [
  { src: resourcePath + "npot-video-1920x1080.mp4" ,
    type: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"',
    // It was found that Firefox's videoHeight doesn't report the
    // correct answer for this video resource, though the uploaded
    // video texture is the correct size.
    expectedHeight: 1080,
  },
  // Should port this to other formats. See tex-image-and-sub-image-2d-with-video.js.
];
var videoNdx = 0;
var videoInfo;
var video;

initTestingHarness();

var vertexShader = [
    '#version 300 es',
    'in vec4 vPosition;',
    'in vec2 texCoord0;',
    'out vec2 texCoord;',
    'void main() {',
    '    gl_Position = vPosition;',
    '    texCoord = texCoord0;',
    '}'].join('\n');

// ESSL 3.00 and WebGL 2.0 are used in order to gain access to the
// "textureSize" built-in function. This was the most reliable way to
// verify the behavior of video-to-texture uploads.

var fragmentShader = [
    '#version 300 es',
    'precision mediump float;',
    'uniform mediump sampler2D tex;',
    'uniform int expectedVideoHeight;',
    'in vec2 texCoord;',
    'out vec4 fragData;',
    'void main() {',
    '    if (textureSize(tex, 0).y == expectedVideoHeight) {',
    '      fragData = vec4(0.0, 1.0, 0.0, 1.0);',
    '    } else {',
    '      fragData = vec4(1.0, 0.0, 0.0, 1.0);',
    '    }',
    '}'].join('\n');

function init()
{
    description('Verify sizing of npot videos uploaded to textures');

    debug('Verifies that the size of a texture, uploaded from a video, is exactly the expected size of the video.');
    debug('Regression test for <a href="http://crbug.com/672895">http://crbug.com/672895</a>');

    var canvas = document.getElementById("example");
    gl = wtu.create3DContext(canvas, { preserveDrawingBuffer: true }, 2);
    wtu.setupUnitQuad(gl);
    var program = wtu.setupProgram(
        gl,
        [vertexShader, fragmentShader],
        ['vPosition', 'texCoord0'],
        [0, 1]);

    if (!program) {
        testFailed("Error creating program");
        return;
    }

    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");
    expectedVideoHeightLoc = gl.getUniformLocation(
        program, "expectedVideoHeight");

    requestAnimationFrame(runNextVideo);
}

function runNextVideo() {
    if (video) {
        video.pause();
    }

    if (videoNdx == videos.length) {
        finishTest();
        return;
    }

    videoInfo = videos[videoNdx++];
    debug("");
    debug("testing: " + videoInfo.type);
    video = document.createElement("video");
    video.muted = true;
    var canPlay = true;
    if (!video.canPlayType) {
        testFailed("video.canPlayType required method missing");
        requestAnimationFrame(runNextVideo);
        return;
    }

    if (!video.canPlayType(videoInfo.type).replace(/no/, '')) {
        debug(videoInfo.type + " unsupported");
        requestAnimationFrame(runNextVideo);
        return;
    };

    document.body.appendChild(video);
    video.style = "display:none;";
    video.type = videoInfo.type;
    video.src = videoInfo.src;
    wtu.startPlayingAndWaitForVideo(video, runTest);
}

function runTest()
{
    var texture = gl.createTexture();
    // Bind the texture to texture unit 0
    gl.bindTexture(gl.TEXTURE_2D, texture);
    // Set up texture parameters
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    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);
    // Set up pixel store parameters
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
    // Upload the video element into the texture
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, video);
    // Point the uniform sampler to texture unit 0
    gl.uniform1i(textureLoc, 0);
    // Set up the expected video size
    debug('video\'s expected height: ' + videoInfo.expectedHeight);
    debug('video\'s reported width and height: ' + video.videoWidth + ' x ' + video.videoHeight);
    // We only verify the height. Chrome was generating the wrong
    // height for some video resources. As it stands, not all browsers
    // match the video's width exactly.
    gl.uniform1i(expectedVideoHeightLoc, videoInfo.expectedHeight);

    // Draw the triangles
    wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);

    // Verify that the video texture's size was as expected
    wtu.checkCanvasRect(gl, 0, 0, gl.canvas.width, gl.canvas.height,
                        [0, 255, 0, 255],
                        "Should be green -- that indicates the video texture's height was correct",
                        1);

    requestAnimationFrame(runNextVideo);
}

</script>
</head>
<body onload="init()">
<canvas id="example" width="32" height="32"></canvas>
<div id="description"></div>
<div id="console"></div>
</body>
</html>
