<style>
canvas {
    width: 300px;
    height: 300px;
}
</style>
</head>
<script id="vertexShaderSource" type="text/glsl">
attribute vec4 a_position;
varying vec2 v_texturePosition;

void main() {
    v_texturePosition = vec2((a_position.x + 1.0) / 2.0, (a_position.y + 1.0) / 2.0);
    gl_Position = a_position;
}
</script>
<script id="fragmentShaderSource" type="text/glsl">
precision mediump float;

varying vec2 v_texturePosition;

uniform sampler2D texture;

void main() {
  gl_FragColor = texture2D(texture, v_texturePosition);
}
</script>
<script>

if (window.testRunner) {
    testRunner.waitUntilDone();
    testRunner.dumpAsText();
}

const width = 300;
const height = 300;
let canvas;
let gl;
let animationFrame = null;
let tested = false;
let drawFunction = null;
let video;

function output(msg) {
    const div = document.getElementById("output");
    div.innerHTML += `${msg}<br>`;
}

function isMostlyRed(buffer, x, y) {
    let offset = (y * width + x) * 4;
    return buffer[offset] > 240 && buffer[offset+1] < 25 && buffer[offset+2] < 25 && buffer[offset+3] > 240;
}

function isMostlyBlue(buffer, x, y) {
    let offset = (y * width + x) * 4;
    return buffer[offset] < 25 && buffer[offset+1] < 25 && buffer[offset+2] > 240 && buffer[offset+3] > 240;
}

function runTest() {
    output("Checking the canvas pixels.");

    drawFunction();
    let pixels = new Uint8Array(width * height * 4);
    gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

    if (isMostlyRed(pixels, 2, 2))
        output("PASS: Bottom edge is red.");
    else
        output("FAIL: Bottom edge is not red.");

    if (isMostlyBlue(pixels, 2, height - 2))
        output("PASS: Top edge is blue.");
    else
        output("FAIL: Top edge is not blue.");

    cancelAnimationFrame(animationFrame);
    video.pause();

    if (window.testRunner)
        testRunner.notifyDone();
}

function init() {

    canvas = document.querySelector("canvas");
    canvas.width = width;
    canvas.height = height;

    gl = canvas.getContext("webgl");

    gl.clearColor(0, 0, 0, 1);

    let vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader, document.getElementById("vertexShaderSource").textContent);
    gl.compileShader(vertexShader);
    if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
        console.error("Vertex Shader failed to compile.");
        console.log(gl.getShaderInfoLog(vertexShader));
        return;
    }

    let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader, document.getElementById("fragmentShaderSource").textContent);
    gl.compileShader(fragmentShader);
    if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
        console.error("Fragment Shader failed to compile.");
        console.log(gl.getShaderInfoLog(fragmentShader));
        return;
    }

    let program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);

    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        console.error("Unable to link shaders into program.");
        return;
    }

    gl.useProgram(program);
    let textureUniform = gl.getUniformLocation(program, "texture");
    let positionAttribute = gl.getAttribLocation(program, "a_position");
    gl.enableVertexAttribArray(positionAttribute);

    // Unlike the corresponding texImage2D-video-flipY-false test, draw a quad using
    // four points in a triangle strip, with 3 floats per point. This way we're doing
    // something different from the WebCore code that renders the video into a texture,
    // ensuring that state restoration is correctly restored.
    let vertices = new Float32Array([-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0, 1.0, 1.0, 0.0]);

    let buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
    gl.vertexAttribPointer(positionAttribute, 3, gl.FLOAT, false, 0, 0);

    let updateTexture = function (texture, data) {
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, data);
        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);

        gl.bindTexture(gl.TEXTURE_2D, null);
    }

    let texture = gl.createTexture();

    video = document.createElement("video");
    video.loop = true;
    video.playsInline = true;

    video.addEventListener("canplay", function () {
        output("Video can play.");
    }, false);

    video.addEventListener("timeupdate", function () {
        // If we've just started, jump forward to 3 seconds. If we've played a bit after
        // that, check the pixels.
        if (video.currentTime < 1) {
            video.currentTime = 3;
            return;
        } else if (video.currentTime > 3.1) {
            if (!tested)
                runTest();
            tested = true;
        }
    }, false);

    output("Setting video src.");
    window.source = new MediaSource();
    source.addEventListener('sourceopen', async event => {
        var buffer = source.addSourceBuffer('video/mp4');
        var response = await fetch('resources/orientation-normal-fragmented.mp4');
        buffer.appendBuffer(await response.arrayBuffer());
    });
    video.srcObject = source;
    video.play();

    drawFunction = function () {
        gl.clear(gl.COLOR_BUFFER_BIT);

        if (video.currentTime > 0) {
            updateTexture(texture, video);
        }

        gl.activeTexture(gl.TEXTURE0);
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.uniform1i(textureUniform, 0);

        gl.bindBuffer(gl.ARRAY_BUFFER, buffer);

        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

        animationFrame = requestAnimationFrame(drawFunction);
    };

    drawFunction();
}

window.addEventListener("load", init, false);
</script>
<body>
    <canvas></canvas>
    <div id="output">
    </div>
</body>